@@ -87,6 +87,10 @@ void fel_writel(feldev_handle *dev, uint32_t addr, uint32_t val);
8787#define H6_CCM_SPI_BGR (0x03001000 + 0x96C)
8888#define H6_CCM_SPI0_GATE_RESET (1 << 0 | 1 << 16)
8989
90+ #define SUN55I_CCM_SPI0_CLK (0x02001000 + 0x940)
91+ #define SUN55I_CCM_SPI_BGR (0x02001000 + 0x96C)
92+ #define SUN55I_CCM_SPI0_GATE_RESET (1 << 0 | 1 << 16)
93+
9094#define SUNIV_GPC_SPI0 (2)
9195#define SUNXI_GPC_SPI0 (3)
9296#define SUN50I_GPC_SPI0 (4)
@@ -131,6 +135,8 @@ static uint32_t gpio_base(feldev_handle *dev)
131135 case 0x1728 : /* H6 */
132136 case 0x1823 : /* H616 */
133137 return 0x0300B000 ;
138+ case 0x1890 : /* A523 */
139+ return 0x02000000 ;
134140 default :
135141 return 0x01C20800 ;
136142 }
@@ -151,22 +157,36 @@ static uint32_t spi_base(feldev_handle *dev)
151157 case 0x1728 : /* H6 */
152158 case 0x1823 : /* H616 */
153159 return 0x05010000 ;
160+ case 0x1890 : /* A523 */
161+ return 0x04025000 ;
154162 default :
155163 return 0x01C68000 ;
156164 }
157165}
158166
167+ static uint32_t gpio_port_stride (feldev_handle * dev )
168+ {
169+ soc_info_t * soc_info = dev -> soc_info ;
170+ switch (soc_info -> soc_id ) {
171+ case 0x1890 : /* A523 */
172+ return 0x30 ;
173+ default :
174+ return 0x24 ;
175+ }
176+ }
177+
159178/*
160- * Configure pin function on a GPIO port
179+ * Configure pin function on a GPIO port.
180+ * Mux fields are 4 bits wide on all sunxi SoCs (pin_idx * 4 bit offset).
161181 */
162182static void gpio_set_cfgpin (feldev_handle * dev , int port_num , int pin_num ,
163183 int val )
164184{
165- uint32_t port_base = gpio_base (dev ) + port_num * 0x24 ;
185+ uint32_t port_base = gpio_base (dev ) + port_num * gpio_port_stride ( dev ) ;
166186 uint32_t cfg_reg = port_base + 4 * (pin_num / 8 );
167187 uint32_t pin_idx = pin_num % 8 ;
168188 uint32_t x = readl (cfg_reg );
169- x &= ~(0x7 << (pin_idx * 4 ));
189+ x &= ~(0xf << (pin_idx * 4 ));
170190 x |= val << (pin_idx * 4 );
171191 writel (x , cfg_reg );
172192}
@@ -198,6 +218,17 @@ static bool soc_is_h6_style(feldev_handle *dev)
198218 }
199219}
200220
221+ static bool soc_is_a523_style (feldev_handle * dev )
222+ {
223+ soc_info_t * soc_info = dev -> soc_info ;
224+ switch (soc_info -> soc_id ) {
225+ case 0x1890 : /* A523 */
226+ return true;
227+ default :
228+ return false;
229+ }
230+ }
231+
201232/*
202233 * Init the SPI0 controller and setup pins muxing.
203234 */
@@ -259,13 +290,23 @@ static bool spi0_init(feldev_handle *dev)
259290 gpio_set_cfgpin (dev , PC , 3 , SUN50I_GPC_SPI0 ); /* SPI0_CS0 */
260291 gpio_set_cfgpin (dev , PC , 4 , SUN50I_GPC_SPI0 ); /* SPI0_MISO */
261292 break ;
293+ case 0x1890 : /* Allwinner A523 */
294+ gpio_set_cfgpin (dev , PC , 12 , SUN50I_GPC_SPI0 ); /* SPI0_CLK */
295+ gpio_set_cfgpin (dev , PC , 2 , SUN50I_GPC_SPI0 ); /* SPI0_MOSI */
296+ gpio_set_cfgpin (dev , PC , 3 , SUN50I_GPC_SPI0 ); /* SPI0_CS0 */
297+ gpio_set_cfgpin (dev , PC , 4 , SUN50I_GPC_SPI0 ); /* SPI0_MISO */
298+ break ;
262299 default : /* Unknown/Unsupported SoC */
263300 printf ("SPI support not implemented yet for %x (%s)!\n" ,
264301 soc_info -> soc_id , soc_info -> name );
265302 return false;
266303 }
267304
268- if (soc_is_h6_style (dev )) {
305+ if (soc_is_a523_style (dev )) {
306+ reg_val = readl (SUN55I_CCM_SPI_BGR );
307+ reg_val |= SUN55I_CCM_SPI0_GATE_RESET ;
308+ writel (reg_val , SUN55I_CCM_SPI_BGR );
309+ } else if (soc_is_h6_style (dev )) {
269310 reg_val = readl (H6_CCM_SPI_BGR );
270311 reg_val |= H6_CCM_SPI0_GATE_RESET ;
271312 writel (reg_val , H6_CCM_SPI_BGR );
@@ -302,7 +343,8 @@ static bool spi0_init(feldev_handle *dev)
302343 spi_is_sun6i (dev ) ? SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL );
303344 /* Choose 24MHz from OSC24M and enable clock */
304345 writel (1U << 31 ,
305- soc_is_h6_style (dev ) ? H6_CCM_SPI0_CLK : CCM_SPI0_CLK );
346+ soc_is_a523_style (dev ) ? SUN55I_CCM_SPI0_CLK :
347+ soc_is_h6_style (dev ) ? H6_CCM_SPI0_CLK : CCM_SPI0_CLK );
306348 }
307349
308350 if (spi_is_sun6i (dev )) {
0 commit comments