+++ /dev/null
-#include <asm/addrspace.h>\r
-#include <asm/types.h>\r
-#include <config.h>\r
-#include <ar7240_soc.h>\r
-\r
-#define REG_OFFSET 4\r
-\r
-/* === END OF CONFIG === */\r
-\r
-/* register offset */\r
-#define OFS_RCV_BUFFER (0*REG_OFFSET)\r
-#define OFS_TRANS_HOLD (0*REG_OFFSET)\r
-#define OFS_SEND_BUFFER (0*REG_OFFSET)\r
-#define OFS_INTR_ENABLE (1*REG_OFFSET)\r
-#define OFS_INTR_ID (2*REG_OFFSET)\r
-#define OFS_DATA_FORMAT (3*REG_OFFSET)\r
-#define OFS_LINE_CONTROL (3*REG_OFFSET)\r
-#define OFS_MODEM_CONTROL (4*REG_OFFSET)\r
-#define OFS_RS232_OUTPUT (4*REG_OFFSET)\r
-#define OFS_LINE_STATUS (5*REG_OFFSET)\r
-#define OFS_MODEM_STATUS (6*REG_OFFSET)\r
-#define OFS_RS232_INPUT (6*REG_OFFSET)\r
-#define OFS_SCRATCH_PAD (7*REG_OFFSET)\r
-\r
-#define OFS_DIVISOR_LSB (0*REG_OFFSET)\r
-#define OFS_DIVISOR_MSB (1*REG_OFFSET)\r
-\r
-#define MY_WRITE(y, z) ((*((volatile u32*)(y))) = z)\r
-#define UART16550_READ(y) ar7240_reg_rd((AR7240_UART_BASE+y))\r
-#define UART16550_WRITE(x, z) ar7240_reg_wr((AR7240_UART_BASE+x), z)\r
-\r
-/*\r
- * This is taken from [Linux]/include/linux/kernel.h\r
- * Keep the name unchanged here\r
- * When this project decides to include that kernel.h some time,\r
- * this would be found "automatically" and be removed hopefully\r
- */\r
-#define DIV_ROUND_CLOSEST(x, divisor)( \\r
-{ \\r
- typeof(divisor) __divisor = divisor; \\r
- (((x) + ((__divisor) / 2)) / (__divisor)); \\r
-} \\r
-)\r
-\r
-/*\r
- * Get CPU, RAM and AHB clocks\r
- * Based on: Linux/arch/mips/ath79/clock.c\r
- */\r
-void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq){\r
-#ifdef CONFIG_WASP\r
- u32 ref_rate, pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv, cpu_pll, ddr_pll;\r
-\r
- // determine reference clock (25 or 40 MHz)\r
- pll = ar7240_reg_rd(RST_BOOTSTRAP_ADDRESS);\r
-\r
- if(pll & 0x10){ // bit 4 == 1 -> REF_CLK == 40 MHz\r
- ref_rate = 40000000;\r
- } else {\r
- ref_rate = 25000000;\r
- }\r
-\r
- pll = ar7240_reg_rd(DPLL2_ADDRESS_c4);\r
-\r
- // CPU PLL from SRIF?\r
- if(pll & (1 << 30)){\r
-\r
- out_div = (pll >> 13) & 0x7;\r
- pll = ar7240_reg_rd(0x181161c0);\r
- nint = (pll >> 18) & 0x1ff;\r
- //nfrac = pll & 0x0003ffff;\r
- ref_div = (pll >> 27) & 0x1f;\r
- //frac = 1 << 18;\r
-\r
- } else {\r
- // only for tests\r
- // TODO: fix me\r
- *cpu_freq = 560000000;\r
- *ddr_freq = 400000000;\r
- *ahb_freq = 200000000;\r
- return;\r
- }\r
-\r
- cpu_pll = (ref_rate / ref_div) * nint;\r
- cpu_pll /= (1 << out_div);\r
-\r
- // DDR PLL from SRIF?\r
- pll = ar7240_reg_rd(DPLL2_ADDRESS_44);\r
-\r
- if (pll & (1 << 30)) {\r
-\r
- out_div = (pll >> 13) & 0x7;\r
- pll = ar7240_reg_rd(0x18116240);\r
- nint = (pll >> 18) & 0x1ff;\r
- //nfrac = pll & 0x0003ffff;\r
- ref_div = (pll >> 27) & 0x1f;\r
- //frac = 1 << 18;\r
-\r
- } else {\r
- // only for tests\r
- // TODO: fix me\r
- *cpu_freq = 560000000;\r
- *ddr_freq = 400000000;\r
- *ahb_freq = 200000000;\r
- return;\r
- }\r
-\r
- ddr_pll = (ref_rate / ref_div) * nint;\r
- ddr_pll /= (1 << out_div);\r
-\r
- clk_ctrl = ar7240_reg_rd(AR934X_CPU_DDR_CLOCK_CONTROL);\r
-\r
- postdiv = (clk_ctrl >> 5) & 0x1f;\r
-\r
- // CPU CLK\r
- if(clk_ctrl & (1 << 2)){ // CPU_PLL_BYPASS\r
- *cpu_freq = ref_rate;\r
- } else if(clk_ctrl & (1 << 20)){ // CPU CLK is derived from CPU_PLL\r
- *cpu_freq = cpu_pll / (postdiv + 1);\r
- } else { // CPU CLK is derived from DDR_PLL\r
- *cpu_freq = ddr_pll / (postdiv + 1);\r
- }\r
-\r
- postdiv = (clk_ctrl >> 10) & 0x1f;\r
-\r
- // DDR CLK\r
- if(clk_ctrl & (1 << 3)){ // DDR_PLL_BYPASS\r
- *ddr_freq = ref_rate;\r
- } else if(clk_ctrl & (1 << 21)){ // DDR CLK is derived from DDR_PLL\r
- *ddr_freq = ddr_pll / (postdiv + 1);\r
- } else { // DDR CLK is derived from CPU_PLL\r
- *ddr_freq = cpu_pll / (postdiv + 1);\r
- }\r
-\r
- postdiv = (clk_ctrl >> 15) & 0x1f;\r
-\r
- // AHB CLK\r
- if(clk_ctrl & (1 << 4)){ // AHB_PLL_BYPASS\r
- *ahb_freq = ref_rate;\r
- } else if(clk_ctrl & (1 << 24)){ // AHB CLK is derived from DDR_PLL\r
- *ahb_freq = ddr_pll / (postdiv + 1);\r
- } else { // AHB CLK is derived from CPU_PLL\r
- *ahb_freq = cpu_pll / (postdiv + 1);\r
- }\r
-\r
-#else\r
- u32 pll, pll_div, ref_div, ahb_div, ddr_div, freq;\r
-\r
- pll = ar7240_reg_rd(AR7240_CPU_PLL_CONFIG);\r
-\r
- pll_div = ((pll & PLL_CONFIG_PLL_DIV_MASK) >> PLL_CONFIG_PLL_DIV_SHIFT);\r
- ref_div = ((pll & PLL_CONFIG_PLL_REF_DIV_MASK) >> PLL_CONFIG_PLL_REF_DIV_SHIFT);\r
- ddr_div = ((pll & PLL_CONFIG_DDR_DIV_MASK) >> PLL_CONFIG_DDR_DIV_SHIFT) + 1;\r
- ahb_div = (((pll & PLL_CONFIG_AHB_DIV_MASK) >> PLL_CONFIG_AHB_DIV_SHIFT) + 1) * 2;\r
-\r
- freq = pll_div * ref_div * 5000000;\r
-\r
- if(cpu_freq){\r
- *cpu_freq = freq;\r
- }\r
-\r
- if(ddr_freq){\r
- *ddr_freq = freq/ddr_div;\r
- }\r
-\r
- if(ahb_freq){\r
- *ahb_freq = freq/ahb_div;\r
- }\r
-#endif\r
-}\r
-\r
-int serial_init(void){\r
- u32 div, val;\r
-#ifdef CONFIG_WASP\r
- val = ar7240_reg_rd(WASP_BOOTSTRAP_REG);\r
-\r
- if((val & WASP_REF_CLK_25) == 0){\r
- div = DIV_ROUND_CLOSEST((25 * 1000000), (16 * CONFIG_BAUDRATE));\r
- } else {\r
- div = DIV_ROUND_CLOSEST((40 * 1000000), (16 * CONFIG_BAUDRATE));\r
- }\r
-#else\r
- u32 ahb_freq, ddr_freq, cpu_freq;\r
-\r
- ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);\r
-\r
- div = DIV_ROUND_CLOSEST(ahb_freq, (16 * CONFIG_BAUDRATE));\r
-\r
- MY_WRITE(0xb8040000, 0xcff);\r
- MY_WRITE(0xb8040008, 0x3b);\r
-\r
- val = ar7240_reg_rd(0xb8040028);\r
- MY_WRITE(0xb8040028,(val | 0x8002));\r
-\r
- MY_WRITE(0xb8040008, 0x2f);\r
-#endif\r
-\r
- /*\r
- * set DIAB bit\r
- */\r
- UART16550_WRITE(OFS_LINE_CONTROL, 0x80);\r
-\r
- /* set divisor */\r
- UART16550_WRITE(OFS_DIVISOR_LSB, (div & 0xff));\r
- UART16550_WRITE(OFS_DIVISOR_MSB, ((div >> 8) & 0xff));\r
-\r
- /* clear DIAB bit*/\r
- UART16550_WRITE(OFS_LINE_CONTROL, 0x00);\r
-\r
- /* set data format */\r
- UART16550_WRITE(OFS_DATA_FORMAT, 0x3);\r
-\r
- UART16550_WRITE(OFS_INTR_ENABLE, 0);\r
-\r
- return(0);\r
-}\r
-\r
-int serial_tstc(void){\r
- return(UART16550_READ(OFS_LINE_STATUS) & 0x1);\r
-}\r
-\r
-u8 serial_getc(void){\r
- while(!serial_tstc());\r
- return(UART16550_READ(OFS_RCV_BUFFER));\r
-}\r
-\r
-void serial_putc(u8 byte){\r
- if(byte == '\n'){\r
- serial_putc('\r');\r
- }\r
-\r
- while(((UART16550_READ(OFS_LINE_STATUS)) & 0x20) == 0x0);\r
-\r
- UART16550_WRITE(OFS_SEND_BUFFER, byte);\r
-}\r
-\r
-void serial_puts(const char *s){\r
- while(*s){\r
- serial_putc(*s++);\r
- }\r
-}\r
+++ /dev/null
-/*
- * Atheros AR933x clocks helper functions
- *
- * Copyright (C) 2014 Piotr Dymacz <piotr@dymacz.pl>
- * Copyright (C) 2014 Mantas Pucka <mantas@8devices.com>
- *
- * SPDX-License-Identifier:GPL-2.0
- */
-
-#include <config.h>
-#include <common.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-#include <asm/ar933x.h>
-
-inline int ar933x_40MHz_xtal(void)
-{
- return (ar933x_reg_read(BOOTSTRAP_STATUS_REG) & BOOTSTRAP_SEL_25_40M_MASK);
-}
-
-/*
- * Get CPU, RAM and AHB clocks
- * Based on: Linux/arch/mips/ath79/clock.c
- */
-void ar933x_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq)
-{
- u32 ref_rate, clock_ctrl, cpu_config, pll, temp;
-
- if(ar933x_40MHz_xtal() == 1){
- ref_rate = 40000000;
- } else {
- ref_rate = 25000000;
- }
-
- /*
- * Read CPU CLock Control Register (CLOCK_CONTROL) value
- */
- clock_ctrl = ar933x_reg_read(CPU_CLOCK_CONTROL_REG);
-
- if(clock_ctrl & CPU_CLOCK_CONTROL_BYPASS_MASK){
- /* PLL is bypassed, so all clocks are == reference clock */
- *cpu_freq = ref_rate;
- *ddr_freq = ref_rate;
- *ahb_freq = ref_rate;
- } else {
- /* read CPU PLL Configuration register (CPU_PLL_CONFIG) value */
- cpu_config = ar933x_reg_read(CPU_PLL_CONFIG_REG);
-
- /* REFDIV */
- temp = (cpu_config & CPU_PLL_CONFIG_REFDIV_MASK)
- >> CPU_PLL_CONFIG_REFDIV_SHIFT;
- pll = ref_rate / temp;
-
- /* DIV_INT (multiplier) */
- temp = (cpu_config & CPU_PLL_CONFIG_DIV_INT_MASK)
- >> CPU_PLL_CONFIG_DIV_INT_SHIFT;
- pll *= temp;
-
- /* OUTDIV */
- temp = (cpu_config & CPU_PLL_CONFIG_OUTDIV_MASK)
- >> CPU_PLL_CONFIG_OUTDIV_SHIFT;
-
- /* Value 0 is not allowed */
- if(temp == 0){
- temp = 1;
- }
-
- pll >>= temp;
-
- /* CPU clock divider */
- temp = ((clock_ctrl & CPU_CLOCK_CONTROL_CPU_POST_DIV_MASK)
- >> CPU_CLOCK_CONTROL_CPU_POST_DIV_SHIFT) + 1;
- *cpu_freq = pll / temp;
-
- /* DDR clock divider */
- temp = ((clock_ctrl & CPU_CLOCK_CONTROL_DDR_POST_DIV_MASK)
- >> CPU_CLOCK_CONTROL_DDR_POST_DIV_SHIFT) + 1;
- *ddr_freq = pll / temp;
-
- /* AHB clock divider */
- temp = ((clock_ctrl & CPU_CLOCK_CONTROL_AHB_POST_DIV_MASK)
- >> CPU_CLOCK_CONTROL_AHB_POST_DIV_SHIFT) + 1;
- *ahb_freq = pll / temp;
- }
-}
+++ /dev/null
-/*
- * Atheros AR933x UART driver
- *
- * Copyright (C) 2014 Piotr Dymacz <piotr@dymacz.pl>
- * Copyright (C) 2008-2010 Atheros Communications Inc.
- *
- * Values for UART_SCALE and UART_STEP:
- * https://www.mail-archive.com/openwrt-devel@lists.openwrt.org/msg22371.html
- *
- * SPDX-License-Identifier:GPL-2.0
- */
-
-#include <config.h>
-#include <common.h>
-#include <asm/addrspace.h>
-#include <asm/ar933x.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static void ar933x_serial_get_scale_step(u32 *uart_scale, u32 *uart_step)
-{
- if(ar933x_40MHz_xtal() == 1){
- switch(gd->baudrate){
- case 600:
- *uart_scale = 255;
- *uart_step = 503;
- break;
- case 1200:
- *uart_scale = 249;
- *uart_step = 983;
- break;
- case 2400:
- *uart_scale = 167;
- *uart_step = 1321;
- break;
- case 4800:
- *uart_scale = 87;
- *uart_step = 1384;
- break;
- case 9600:
- *uart_scale = 45;
- *uart_step = 1447;
- break;
- case 14400:
- *uart_scale = 53;
- *uart_step = 2548;
- break;
- case 19200:
- *uart_scale = 22;
- *uart_step = 1447;
- break;
- case 28800:
- *uart_scale = 26;
- *uart_step = 2548;
- break;
- case 38400:
- *uart_scale = 28;
- *uart_step = 3649;
- break;
- case 56000:
- *uart_scale = 7;
- *uart_step = 1468;
- break;
- case 57600:
- *uart_scale = 34;
- *uart_step = 6606;
- break;
- case 115200:
- *uart_scale = 28;
- *uart_step = 10947;
- break;
- case 128000:
- *uart_scale = 6;
- *uart_step = 2936;
- break;
- case 153600:
- *uart_scale = 18;
- *uart_step = 9563;
- break;
- case 230400:
- *uart_scale = 16;
- *uart_step = 12834;
- break;
- case 250000:
- *uart_scale = 4;
- *uart_step = 4096;
- break;
- case 256000:
- *uart_scale = 6;
- *uart_step = 5872;
- break;
- case 460800:
- *uart_scale = 7;
- *uart_step = 12079;
- break;
- case 576000:
- *uart_scale = 4;
- *uart_step = 9437;
- break;
- case 921600:
- *uart_scale = 3;
- *uart_step = 12079;
- break;
- case 1000000:
- *uart_scale = 2;
- *uart_step = 9830;
- break;
- case 1152000:
- *uart_scale = 2;
- *uart_step = 11324;
- break;
- case 1500000:
- *uart_scale = 0;
- *uart_step = 4915;
- break;
- case 2000000:
- *uart_scale = 0;
- *uart_step = 6553;
- break;
- default:
- *uart_scale = (40000000 / (16 * gd->baudrate)) - 1;
- *uart_step = 8192;
- }
- } else {
- switch(gd->baudrate){
- case 600:
- *uart_scale = 255;
- *uart_step = 805;
- break;
- case 1200:
- *uart_scale = 209;
- *uart_step = 1321;
- break;
- case 2400:
- *uart_scale = 104;
- *uart_step = 1321;
- break;
- case 4800:
- *uart_scale = 54;
- *uart_step = 1384;
- break;
- case 9600:
- *uart_scale = 78;
- *uart_step = 3976;
- break;
- case 14400:
- *uart_scale = 98;
- *uart_step = 7474;
- break;
- case 19200:
- *uart_scale = 55;
- *uart_step = 5637;
- break;
- case 28800:
- *uart_scale = 77;
- *uart_step = 11777;
- break;
- case 38400:
- *uart_scale = 36;
- *uart_step = 7449;
- break;
- case 56000:
- *uart_scale = 4;
- *uart_step = 1468;
- break;
- case 57600:
- *uart_scale = 35;
- *uart_step = 10871;
- break;
- case 115200:
- *uart_scale = 20;
- *uart_step = 12683;
- break;
- case 128000:
- *uart_scale = 11;
- *uart_step = 8053;
- break;
- case 153600:
- *uart_scale = 9;
- *uart_step = 8053;
- break;
- case 230400:
- *uart_scale = 9;
- *uart_step = 12079;
- break;
- case 250000:
- *uart_scale = 6;
- *uart_step = 9175;
- break;
- case 256000:
- *uart_scale = 5;
- *uart_step = 8053;
- break;
- case 460800:
- *uart_scale = 4;
- *uart_step = 12079;
- break;
- case 576000:
- *uart_scale = 3;
- *uart_step = 12079;
- break;
- case 921600:
- *uart_scale = 1;
- *uart_step = 9663;
- break;
- case 1000000:
- *uart_scale = 1;
- *uart_step = 10485;
- break;
- case 1152000:
- *uart_scale = 1;
- *uart_step = 12079;
- break;
- case 1500000:
- *uart_scale = 0;
- *uart_step = 7864;
- break;
- case 2000000:
- *uart_scale = 0;
- *uart_step = 10485;
- break;
- default:
- *uart_scale = (25000000 / (16 * gd->baudrate)) - 1;
- *uart_step = 8192;
- }
- }
-}
-
-void serial_setbrg(void)
-{
- /* TODO: better clock calculation, baudrate, etc. */
- u32 uart_clock;
- u32 uart_scale;
- u32 uart_step;
-
- ar933x_serial_get_scale_step(&uart_scale, &uart_step);
-
- uart_clock = (uart_scale << UART_CLOCK_SCALE_SHIFT);
- uart_clock |= (uart_step << UART_CLOCK_STEP_SHIFT);
-
- ar933x_reg_write(UART_CLOCK_REG, uart_clock);
-}
-
-int serial_init(void)
-{
- u32 uart_cs;
-
- /*
- * Set GPIO10 (UART_SO) as output and enable UART,
- * BIT(15) in GPIO_FUNCTION_1 register must be written with 1
- */
- ar933x_reg_read_set(GPIO_OE_REG, GPIO10);
-
- ar933x_reg_read_set(GPIO_FUNCTION_1_REG,
- (1 << GPIO_FUNCTION_1_UART_EN_SHIFT) |
- (1 << 15));
-
- /*
- * UART controller configuration:
- * - no DMA
- * - no interrupt
- * - DCE mode
- * - no flow control
- * - set RX ready oride
- * - set TX ready oride
- */
- uart_cs = (0 << UART_CS_DMA_EN_SHIFT) |
- (0 << UART_CS_HOST_INT_EN_SHIFT) |
- (1 << UART_CS_RX_READY_ORIDE_SHIFT) |
- (1 << UART_CS_TX_READY_ORIDE_SHIFT) |
- (UART_CS_IFACE_MODE_DCE_VAL << UART_CS_IFACE_MODE_SHIFT) |
- (UART_CS_FLOW_MODE_NO_VAL << UART_CS_FLOW_MODE_SHIFT);
-
- ar933x_reg_write(UART_CS_REG, uart_cs);
-
- serial_setbrg();
-
- return 0;
-}
-
-void serial_putc(const char c)
-{
- u32 uart_data;
-
- if(c == '\n')
- serial_putc('\r');
-
- /* Wait for FIFO */
- do{
- uart_data = ar933x_reg_read(UART_DATA_REG);
- } while(((uart_data & UART_TX_CSR_MASK) >> UART_TX_CSR_SHIFT) == 0);
-
- /* Put data in buffer and set CSR bit */
- uart_data = (u32)c | (1 << UART_TX_CSR_SHIFT);
-
- ar933x_reg_write(UART_DATA_REG, uart_data);
-}
-
-int serial_getc(void)
-{
- u32 uart_data;
-
- while(!serial_tstc())
- ;
-
- uart_data = ar933x_reg_read(UART_DATA_REG);
-
- ar933x_reg_write(UART_DATA_REG, (1 << UART_RX_CSR_SHIFT));
-
- return (uart_data & UART_TX_RX_DATA_MASK);
-}
-
-int serial_tstc(void)
-{
- u32 uart_data = ar933x_reg_read(UART_DATA_REG);
-
- if((uart_data & UART_RX_CSR_MASK) >> UART_RX_CSR_SHIFT){
- return 1;
- }
-
- return 0;
-}
-
-void serial_puts(const char *s)
-{
- while(*s){
- serial_putc(*s++);
- }
-}