]> the.earth.li Git - esp8266-clock.git/blob - spi.c
Update Makefile to link 2 separate ROMs
[esp8266-clock.git] / spi.c
1 /*
2  * Copyright 2017 Jonathan McDowell <noodles@earth.li>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include <stdint.h>
18
19 #include <os_type.h>
20 #include <gpio.h>
21
22 #include "spi_register.h"
23
24 #define spi_busy(spi_no) (READ_PERI_REG(SPI_CMD(spi_no)) & SPI_USR)
25
26 #define SPI 0
27 #define HSPI 1
28
29 void ICACHE_FLASH_ATTR spi_init(void)
30 {
31         /* SPI clock = CPU clock/160 [(79 + 1) * 2]= 500KHz */
32         WRITE_PERI_REG(SPI_CLOCK(HSPI),
33                 ((79 & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
34                 ((1 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
35                 ((1 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
36                 ((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S));
37
38         /*
39          * We use hardware SPI, but repurpose MISO for CS, as we don't need it.
40          */
41         WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105);
42         PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);      /* GPIO13: MOSI */
43         PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);      /* GPIO14: CLK  */
44         /* FIXME: CS/SS is not this pin */
45         PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);      /* GPIO15 */
46         /* We don't use MISO, repurpose this pin for GPIO12 (used as CS) */
47         PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);
48         PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDI_U);
49         gpio_output_set(0, 0, BIT12, 0);
50
51         /* Configure up our SPI options */
52         SET_PERI_REG_MASK(SPI_USER(HSPI),
53                 SPI_WR_BYTE_ORDER |     /* MSB output first */
54                 SPI_USR_MOSI            /* Enable data (MOSI) output */
55         );
56         CLEAR_PERI_REG_MASK(SPI_USER(HSPI),
57                 SPI_FLASH_MODE |                /* Disable flash mode */
58                 SPI_USR_MISO | SPI_USR_COMMAND |
59                 SPI_USR_ADDR | SPI_USR_DUMMY |  /* Disable non-data output */
60                 SPI_CS_SETUP | SPI_CS_HOLD |    /* We drive our own CS */
61                 SPI_CK_OUT_EDGE                 /* Data valid on CLK leading */
62         );
63         /* Clock low when inactive */
64         CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
65
66         /* We're writing 8 bits at a time */
67         /* TODO: We could write up to 32 bits at once potentially. */
68         WRITE_PERI_REG(SPI_USER1(HSPI),
69                 (7 & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S);
70 }
71
72 void ICACHE_FLASH_ATTR spi_write(size_t len, uint8_t *data)
73 {
74         int i;
75
76         for (i = 0; i < len; i++) {
77                 /* Wait for SPI to be ready */
78                 while (spi_busy(HSPI));
79
80                 /* We just write the top 8 bits of the 32 bit value */
81                 WRITE_PERI_REG(SPI_W0(HSPI), data[i] << 24);
82
83                 /* Begin the SPI transaction */
84                 SET_PERI_REG_MASK(SPI_CMD(HSPI), SPI_USR);
85         }
86
87         /* Don't return until it's done */
88         while (spi_busy(HSPI));
89 }