Semi-decennial update. 50% code inflation.
[cbaos.git] / arch / arm-cortex-m3 / mach-lpc13xx / board_lpcxpresso.c
bloba1a015b9a85d17082b159b3b34e5c28e23ecaa01
1 /* Author: Domen Puncer Kugler <domen@cba.si>. License: WTFPL, see file LICENSE */
2 #include <board.h>
3 #include <mach/lpc13xx_regs.h>
4 #include <mach/lpc13xx_interrupt.h>
5 #include <gpio.h>
6 #include <mach/lpc13xx_gpio.h>
7 #include <interrupt.h>
8 #include <drivers/lpc_serial.h>
9 #include <drivers/lpc_serial_proper.h>
10 #include <drivers/lpc_ssp.h>
11 #include <drivers/lpc_i2c.h>
12 #include <device.h>
14 #ifdef CONFIG_USBDONGLE
15 #define LPC1343_SERIAL /* fancy serial, disables the console */
16 #else
17 #define LPC1343_SSP
18 #define LPC1343_I2C
19 #endif
22 void tty0_init()
24 #ifdef LPC1343_SERIAL
25 #ifdef CONFIG_USBDONGLE_PCB1 /* SPI pins are used on PCB1 */
26 /* printf over SPI */
27 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;
28 LPC_IOCON->PIO0_8 = 1; /* MISO */
29 LPC_IOCON->PIO0_9 = 1; /* MOSI */
30 LPC_IOCON->SCKLOC = 0; /* SCK on P0_10 */
31 LPC_IOCON->JTAG_TCK_PIO0_10 = 2; /* SCK */
32 LPC_IOCON->PIO0_2 = 1; /* SSEL */
34 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_SSP;
35 LPC_SYSCON->SSPCLKDIV = 1;
37 LPC_SYSCON->PRESETCTRL |= 1<<0;
39 extern struct driver serial_spi_driver;
40 static struct device tty0;
41 tty0.name = "tty0";
42 tty0.drv = &serial_spi_driver;
43 if (tty0.drv->probe(&tty0, NULL) == 0)
44 device_register(&tty0);
45 #endif
46 #else
47 static struct device tty0;
48 static struct lpc_uart_data uart_data;
50 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;
51 LPC_IOCON->PIO1_6 = 1; /* uart RXD */
52 LPC_IOCON->PIO1_7 = 1; /* uart TXD */
54 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_UART;
55 LPC_SYSCON->UARTCLKDIV = 1; /* main clock / 1 */
57 uart_data.base = (void*)LPC_UART_BASE;
58 uart_data.flags = LPC_UART_FDR;
59 uart_data.pclk = CONFIG_FCPU;
60 uart_data.baudrate = 115200;
62 tty0.name = "tty0";
63 tty0.drv = &serial_driver;
64 if (tty0.drv->probe(&tty0, &uart_data) == 0)
65 device_register(&tty0);
66 #endif
69 #ifdef LPC1343_SERIAL
70 static void serial_init()
72 // if this is enabed the tty0 above needs to be disabled
73 static struct device serial;
74 static struct lpc_uart_proper_data uart_data;
75 static u8 buf_rx_data[1024];
76 static u8 buf_tx_data[64+1];
78 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;
79 LPC_IOCON->PIO1_6 = 1; /* uart RXD */
80 LPC_IOCON->PIO1_7 = 1; /* uart TXD */
82 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_UART;
83 LPC_SYSCON->UARTCLKDIV = 1; /* main clock / 1 */
85 uart_data.base = (void*)LPC_UART_BASE;
86 uart_data.flags = LPC_UART_FDR;
87 uart_data.pclk = CONFIG_FCPU;
88 uart_data.baudrate = 115200;
89 uart_data.irq = IRQ_UART;
90 circ_buf_init(&uart_data.rx_buf, buf_rx_data, sizeof(buf_rx_data));
91 circ_buf_init(&uart_data.tx_buf, buf_tx_data, sizeof(buf_tx_data));
93 serial.name = "serial";
94 serial.drv = &serial_driver_proper;
95 if (serial.drv->probe(&serial, &uart_data) == 0)
96 device_register(&serial);
98 #else
99 static void serial_init() { }
100 #endif
102 void udelay(int x)
104 x = x*(CONFIG_FCPU/1000000)/4;
105 asm volatile(
106 "mov %0, %1\n\t"
107 ".udelay_%=:\n\t"
108 "subs %0, %0, #1\n\t" /* 1 cycle */
109 "bne .udelay_%=\n\t" /* 3 cycles */
110 : "=r" (x) : "r" (x) : "cc" );
113 #ifdef LPC1343_SSP
114 static struct lpc_ssp_data lpc_ssp_data;
116 struct spi_master spi0 = {
117 .spi = (void*)LPC_SSP_BASE,
118 .spi_data = &lpc_ssp_data,
119 /* last_dev implicitly initialized */
122 static int board_ssp_init()
125 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;
126 gpio_init(GPIO_0_8_MISO, 0, 0);
127 gpio_init(GPIO_0_9_MOSI, 0, 0);
128 // LPC_IOCON->PIO0_8 = 1; /* MISO */
129 // LPC_IOCON->PIO0_9 = 1; /* MOSI */
130 LPC_IOCON->SCKLOC = 0; /* SCK on P0_10 */
131 //gpio_init(GPIO_0_10_SCK, 0, 0);
132 LPC_IOCON->SCKLOC = 2; /* SCK on P0_6 */
133 gpio_init(GPIO_0_6_SCK, 0, 0);
134 // LPC_IOCON->JTAG_TCK_PIO0_10 = 2; /* SCK */
136 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_SSP;
137 LPC_SYSCON->SSPCLKDIV = 1;
139 LPC_SYSCON->PRESETCTRL |= 1<<0;
141 lpc_ssp_data.pclk = CONFIG_FCPU;
142 lpc_ssp_data.irq = IRQ_SSP;
143 lpc_ssp_register(&spi0);
144 spi_register_master(&spi0);
146 return 0;
148 #else
149 static int board_ssp_init() { return 0; }
150 #endif
152 #ifdef LPC1343_I2C
153 static struct lpc_i2c lpc_i2c_data0;
155 struct i2c_master i2c0 = {
156 .priv = &lpc_i2c_data0,
157 .speed = 400000,
160 static int board_i2c0_init()
162 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;
163 LPC_IOCON->PIO0_4 = 1; /* SCL */
164 LPC_IOCON->PIO0_5 = 1; /* SDA */
166 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_I2C;
168 LPC_SYSCON->PRESETCTRL |= 1<<1;
170 lpc_i2c_data0.regs = (void*)LPC_I2C_BASE;
171 lpc_i2c_data0.pclk = CONFIG_FCPU; /* system clock, which could be different from main clock */
172 lpc_i2c_data0.irq = IRQ_I2C;
173 lpc_i2c_data0.bus = 0;
174 lpc_i2c_register(&i2c0);
175 i2c_register_master(&i2c0);
177 return 0;
179 #else
180 static int board_i2c0_init() { return 0; }
181 #endif
183 void board_init()
185 /* power up IRC */
186 LPC_SYSCON->PDRUNCFG &= ~(PDRUNCFG_IRCOUT_PD | PDRUNCFG_IRC_PD);
188 /* select IRC for main clock */
189 LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_IRC;
190 LPC_SYSCON->MAINCLKUEN = 0;
191 LPC_SYSCON->MAINCLKUEN = 1;
193 /* IRC clock for PLL */
194 LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_IRC;
195 LPC_SYSCON->SYSPLLCLKUEN = 0;
196 LPC_SYSCON->SYSPLLCLKUEN = 1;
198 /* for mode 1: Fclkout = M * Fclkin = Fcco/(2*P)
199 * Fclkin (IRC) = 12MHz, Fcco e [156, 320] */
200 #if CONFIG_FCPU == 72000000
201 LPC_SYSCON->SYSPLLCTRL = 1<<5 /* P=2 */ | 5<<0 /* M=6 */; /* set clock to 72 MHz */
202 #elif CONFIG_FCPU == 48000000
203 LPC_SYSCON->SYSPLLCTRL = 1<<5 /* P=2 */ | 3<<0 /* M=4 */; /* set clock to 48 MHz */
204 #elif CONFIG_FCPU == 12000000
205 #else
206 #error "invalid CONFIG_FCPU"
207 #endif
209 #if CONFIG_FCPU > 40000000
210 FLASHCFG = (FLASHCFG & ~3) | 2; /* 3 system clocks */
211 #elif CONFIG_FCPU > 20000000
212 FLASHCFG = (FLASHCFG & ~3) | 1; /* 2 system clocks */
213 #else
214 FLASHCFG = (FLASHCFG & ~3) | 0; /* 1 system clocks */
215 #endif
217 /* power up SYSPLL */
218 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_SYSPLL_PD;
219 /* wait for PLL lock */
220 while ((LPC_SYSCON->SYSPLLSTAT & 1) == 0)
223 #if CONFIG_FCPU != 12000000
224 /* select PLL output for main clock */
225 LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_PLL;
226 LPC_SYSCON->MAINCLKUEN = 0;
227 LPC_SYSCON->MAINCLKUEN = 1;
228 #endif
230 serial_init();
231 board_ssp_init();
232 board_i2c0_init();
234 /* set-up interrupt on P2_9 transitioning to low - cbashell entry */
235 #if 0
236 // XXX this doesn't work btw.
237 gpio_init(GPIO_2_9, GPIO_INPUT, 0);
238 LPC_IOCON->PIO2_9 = 0x50; /* pull-up */
239 LPC_GPIO2->IEV |= 0<<9; /* falling edge */
240 LPC_GPIO2->IE |= 1<<9; /* enable interrupt */
241 irq_enable(IRQ_WAKEUP_2_9);
242 #endif