summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/config/sansafuzeplus.h5
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.c16
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.h27
-rw-r--r--firmware/target/arm/imx233/mmc-imx233.c146
-rw-r--r--firmware/target/arm/imx233/sd-imx233.c2
-rw-r--r--firmware/target/arm/imx233/ssp-imx233.c61
-rw-r--r--firmware/target/arm/imx233/ssp-imx233.h13
-rw-r--r--firmware/target/arm/imx233/system-imx233.c29
-rw-r--r--firmware/target/arm/imx233/system-target.h41
-rw-r--r--firmware/target/arm/imx233/usb-imx233.c1
10 files changed, 291 insertions, 50 deletions
diff --git a/firmware/export/config/sansafuzeplus.h b/firmware/export/config/sansafuzeplus.h
index 680f7cfd2d..5a78d37056 100644
--- a/firmware/export/config/sansafuzeplus.h
+++ b/firmware/export/config/sansafuzeplus.h
@@ -171,12 +171,15 @@
171#define HAVE_USBSTACK 171#define HAVE_USBSTACK
172//#define USB_HANDLED_BY_OF 172//#define USB_HANDLED_BY_OF
173#define USE_ROCKBOX_USB 173#define USE_ROCKBOX_USB
174#define HAVE_BOOTLOADER_USB_MODE
175#define USB_VENDOR_ID 0x0781 174#define USB_VENDOR_ID 0x0781
176#define USB_PRODUCT_ID 0x74e1 175#define USB_PRODUCT_ID 0x74e1
177#define HAVE_USB_HID_MOUSE 176#define HAVE_USB_HID_MOUSE
178//#define HAVE_BOOTLOADER_USB_MODE 177//#define HAVE_BOOTLOADER_USB_MODE
179 178
179/* The fuze+ actually interesting partition table does not use 512-byte sector
180 * (usually 2048 logical sector size) */
181#define MAX_LOG_SECTOR_SIZE 2048
182
180/* Define this if you have adjustable CPU frequency */ 183/* Define this if you have adjustable CPU frequency */
181#define HAVE_ADJUSTABLE_CPU_FREQ 184#define HAVE_ADJUSTABLE_CPU_FREQ
182 185
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.c b/firmware/target/arm/imx233/clkctrl-imx233.c
index 7701b84c41..ee77a77493 100644
--- a/firmware/target/arm/imx233/clkctrl-imx233.c
+++ b/firmware/target/arm/imx233/clkctrl-imx233.c
@@ -60,15 +60,25 @@ void imx233_set_clock_divisor(enum imx233_clock_t clk, int div)
60 switch(clk) 60 switch(clk)
61 { 61 {
62 case CLK_PIX: 62 case CLK_PIX:
63 __REG_CLR(HW_CLKCTRL_PIX) = (1 << 12) - 1; 63 __REG_CLR(HW_CLKCTRL_PIX) = HW_CLKCTRL_PIX__DIV_BM;
64 __REG_SET(HW_CLKCTRL_PIX) = div; 64 __REG_SET(HW_CLKCTRL_PIX) = div;
65 while(HW_CLKCTRL_PIX & __CLK_BUSY); 65 while(HW_CLKCTRL_PIX & __CLK_BUSY);
66 break; 66 break;
67 case CLK_SSP: 67 case CLK_SSP:
68 __REG_CLR(HW_CLKCTRL_SSP) = (1 << 9) - 1; 68 __REG_CLR(HW_CLKCTRL_SSP) = HW_CLKCTRL_SSP__DIV_BM;
69 __REG_SET(HW_CLKCTRL_SSP) = div; 69 __REG_SET(HW_CLKCTRL_SSP) = div;
70 while(HW_CLKCTRL_SSP & __CLK_BUSY); 70 while(HW_CLKCTRL_SSP & __CLK_BUSY);
71 break; 71 break;
72 case CLK_CPU:
73 __REG_CLR(HW_CLKCTRL_CPU) = HW_CLKCTRL_CPU__DIV_CPU_BM;
74 __REG_SET(HW_CLKCTRL_CPU) = div;
75 while(HW_CLKCTRL_CPU & HW_CLKCTRL_CPU__BUSY_REF_CPU);
76 break;
77 case CLK_AHB:
78 __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__DIV_BM;
79 __REG_SET(HW_CLKCTRL_HBUS) = div;
80 while(HW_CLKCTRL_HBUS & __CLK_BUSY);
81 break;
72 default: return; 82 default: return;
73 } 83 }
74} 84}
@@ -81,6 +91,7 @@ void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv)
81 { 91 {
82 case CLK_PIX: REG = &HW_CLKCTRL_FRAC_PIX; break; 92 case CLK_PIX: REG = &HW_CLKCTRL_FRAC_PIX; break;
83 case CLK_IO: REG = &HW_CLKCTRL_FRAC_IO; break; 93 case CLK_IO: REG = &HW_CLKCTRL_FRAC_IO; break;
94 case CLK_CPU: REG = &HW_CLKCTRL_FRAC_CPU; break;
84 default: return; 95 default: return;
85 } 96 }
86 97
@@ -97,6 +108,7 @@ void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass)
97 { 108 {
98 case CLK_PIX: msk = HW_CLKCTRL_CLKSEQ__BYPASS_PIX; break; 109 case CLK_PIX: msk = HW_CLKCTRL_CLKSEQ__BYPASS_PIX; break;
99 case CLK_SSP: msk = HW_CLKCTRL_CLKSEQ__BYPASS_SSP; break; 110 case CLK_SSP: msk = HW_CLKCTRL_CLKSEQ__BYPASS_SSP; break;
111 case CLK_CPU: msk = HW_CLKCTRL_CLKSEQ__BYPASS_CPU; break;
100 default: return; 112 default: return;
101 } 113 }
102 114
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.h b/firmware/target/arm/imx233/clkctrl-imx233.h
index 1533b52cce..2a12129171 100644
--- a/firmware/target/arm/imx233/clkctrl-imx233.h
+++ b/firmware/target/arm/imx233/clkctrl-imx233.h
@@ -27,15 +27,34 @@
27 27
28#define HW_CLKCTRL_BASE 0x80040000 28#define HW_CLKCTRL_BASE 0x80040000
29 29
30#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0))
31#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BP 20
32#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BM (3 << 20)
33
34#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10))
35
36#define HW_CLKCTRL_CPU (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
37#define HW_CLKCTRL_CPU__DIV_CPU_BP 0
38#define HW_CLKCTRL_CPU__DIV_CPU_BM 0x3f
39#define HW_CLKCTRL_CPU__BUSY_REF_CPU (1 << 28)
40
41#define HW_CLKCTRL_HBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
42#define HW_CLKCTRL_HBUS__DIV_BP 0
43#define HW_CLKCTRL_HBUS__DIV_BM 0x1f
44
30#define HW_CLKCTRL_XTAL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x50)) 45#define HW_CLKCTRL_XTAL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x50))
31#define HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE (1 << 26) 46#define HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE (1 << 26)
32 47
33#define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60)) 48#define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60))
49#define HW_CLKCTRL_PIX__DIV_BM 0xfff
50
34#define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70)) 51#define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
52#define HW_CLKCTRL_SSP__DIV_BM 0x1ff
35 53
36#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110)) 54#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110))
37#define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1) 55#define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1)
38#define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5) 56#define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5)
57#define HW_CLKCTRL_CLKSEQ__BYPASS_CPU (1 << 7)
39 58
40#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0)) 59#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0))
41#define HW_CLKCTRL_FRAC_CPU (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf0)) 60#define HW_CLKCTRL_FRAC_CPU (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf0))
@@ -52,9 +71,11 @@
52 71
53enum imx233_clock_t 72enum imx233_clock_t
54{ 73{
55 CLK_PIX, 74 CLK_PIX, /* div, frac */
56 CLK_SSP, 75 CLK_SSP, /* div, frac */
57 CLK_IO, 76 CLK_IO, /* div */
77 CLK_CPU, /* div, frac */
78 CLK_AHB /* div */
58}; 79};
59 80
60void imx233_enable_timrot_xtal_clk32k(bool enable); 81void imx233_enable_timrot_xtal_clk32k(bool enable);
diff --git a/firmware/target/arm/imx233/mmc-imx233.c b/firmware/target/arm/imx233/mmc-imx233.c
index f56ff3725c..dafe63f3d3 100644
--- a/firmware/target/arm/imx233/mmc-imx233.c
+++ b/firmware/target/arm/imx233/mmc-imx233.c
@@ -22,36 +22,54 @@
22#include "system.h" 22#include "system.h"
23#include "mmc.h" 23#include "mmc.h"
24#include "sdmmc.h" 24#include "sdmmc.h"
25#include "storage.h"
25#include "ssp-imx233.h" 26#include "ssp-imx233.h"
26#include "pinctrl-imx233.h" 27#include "pinctrl-imx233.h"
27#include "button-target.h" 28#include "button-target.h"
28 29
30/**
31 * This code assumes a single eMMC internal flash
32 */
33
29#ifdef SANSA_FUZEPLUS 34#ifdef SANSA_FUZEPLUS
30#define MMC_SSP 2 35#define MMC_SSP 2
31#else 36#else
32#error You need to configure the ssp to use 37#error You need to configure the ssp to use
33#endif 38#endif
34 39
40#define MMC_RCA 1
41
42/** When set, this values restrict the windows of the read and writes */
43static unsigned mmc_window_start = 0;
44static unsigned mmc_window_end = INT_MAX;
45
46static struct mutex mmc_mutex;
47
35int mmc_init(void) 48int mmc_init(void)
36{ 49{
50 mutex_init(&mmc_mutex);
51
37 imx233_ssp_start(MMC_SSP); 52 imx233_ssp_start(MMC_SSP);
38 imx233_ssp_softreset(MMC_SSP); 53 imx233_ssp_softreset(MMC_SSP);
39 imx233_ssp_set_mode(MMC_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC); 54 imx233_ssp_set_mode(MMC_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC);
40 #ifdef SANSA_FUZEPLUS 55 #ifdef SANSA_FUZEPLUS
41 /** Sansa Fuze+ has an internal eMMC 8-bit wide flash, power gate is pin PWM3 */ 56 /** Sansa Fuze+ has an internal eMMC 8-bit wide flash, power gate is pin PWM3
57 * and power up time is 20ms */
42 imx233_set_pin_function(1, 29, PINCTRL_FUNCTION_GPIO); 58 imx233_set_pin_function(1, 29, PINCTRL_FUNCTION_GPIO);
43 imx233_enable_gpio_output(1, 29, true); 59 imx233_enable_gpio_output(1, 29, true);
44 imx233_set_gpio_output(1, 29, false); 60 imx233_set_gpio_output(1, 29, false);
61 sleep(HZ / 5);
45 62
46 imx233_ssp_setup_ssp2_sd_mmc_pins(true, 8, PINCTRL_DRIVE_8mA); 63 imx233_ssp_setup_ssp2_sd_mmc_pins(true, 8, PINCTRL_DRIVE_8mA);
47 #endif 64 #endif
48 /* SSPCLK @ 120MHz 65 /* SSPCLK @ 96MHz
49 * gives bitrate of 120 / 100 / 3 = 400kHz */ 66 * gives bitrate of 96000 / 240 / 1 = 400kHz */
50 imx233_ssp_set_timings(MMC_SSP, 100, 2); 67 imx233_ssp_set_timings(MMC_SSP, 240, 0, 0xffff);
51 imx233_ssp_set_timeout(MMC_SSP, 0xffff);
52 imx233_ssp_sd_mmc_power_up_sequence(MMC_SSP); 68 imx233_ssp_sd_mmc_power_up_sequence(MMC_SSP);
69 imx233_ssp_set_bus_width(MMC_SSP, 1);
70 imx233_ssp_set_block_size(MMC_SSP, 9);
53 /* go to idle state */ 71 /* go to idle state */
54 int ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, SD_GO_IDLE_STATE, 0, SSP_NO_RESP, NULL, 0, false, NULL); 72 int ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, SD_GO_IDLE_STATE, 0, SSP_NO_RESP, NULL, 0, false, false, NULL);
55 if(ret != 0) 73 if(ret != 0)
56 return -1; 74 return -1;
57 /* send op cond until the card respond with busy bit set; it must complete within 1sec */ 75 /* send op cond until the card respond with busy bit set; it must complete within 1sec */
@@ -59,18 +77,82 @@ int mmc_init(void)
59 do 77 do
60 { 78 {
61 uint32_t ocr; 79 uint32_t ocr;
62 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 1, 0x40ff8000, SSP_SHORT_RESP, NULL, 0, false, &ocr); 80 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 1, 0x40ff8000, SSP_SHORT_RESP, NULL, 0, false, false, &ocr);
63 if(ret == 0 && ocr & (1 << 31)) 81 if(ret == 0 && ocr & (1 << 31))
64 break; 82 break;
65 }while(!TIME_AFTER(current_tick, timeout)); 83 }while(!TIME_AFTER(current_tick, timeout));
66 84
67 if(ret != 0) 85 if(ret != 0)
68 return -2; 86 return -2;
69 87 /* get CID */
70 uint32_t cid[4]; 88 uint32_t cid[4];
71 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 2, 0, SSP_LONG_RESP, NULL, 0, false, cid); 89 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 2, 0, SSP_LONG_RESP, NULL, 0, false, false, cid);
72 if(ret != 0) 90 if(ret != 0)
73 return -3; 91 return -3;
92 /* Set RCA */
93 uint32_t status;
94 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 3, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status);
95 if(ret != 0)
96 return -4;
97 /* Select card */
98 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 7, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status);
99 if(ret != 0)
100 return -5;
101 /* Check TRAN state */
102 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 13, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status);
103 if(ret != 0)
104 return -6;
105 if(((status >> 9) & 0xf) != 4)
106 return -7;
107 /* Switch to 8-bit bus */
108 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 6, 0x3b70200, SSP_SHORT_RESP, NULL, 0, true, false, &status);
109 if(ret != 0)
110 return -8;
111 /* switch error ? */
112 if(status & 0x80)
113 return -9;
114 imx233_ssp_set_bus_width(MMC_SSP, 8);
115 /* Switch to high speed mode */
116 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 6, 0x3b90100, SSP_SHORT_RESP, NULL, 0, true, false, &status);
117 if(ret != 0)
118 return -10;
119 /* switch error ?*/
120 if(status & 0x80)
121 return -11;
122 /* SSPCLK @ 96MHz
123 * gives bitrate of 96 / 2 / 1 = 48MHz */
124 imx233_ssp_set_timings(MMC_SSP, 2, 0, 0xffff);
125
126 #ifdef SANSA_FUZEPLUS
127 /**
128 * The Fuze+ uses a strange layout: is has a first MBR at sector 0 with four entries:
129 * 1) Actual user partition
130 * 2) Sigmatel boot partition
131 * 3)4) Other (certificate related ?) partitions
132 * The partition 1) has type 1 but it's actually a type 5 (logical partition) with
133 * a second partition table with usually one entry which is the FAT32 one.
134 * The first table uses 512-byte sector size and the second one usually uses
135 * 2048-byte logical sector size.
136 *
137 * We restrict mmc window to the user partition */
138 uint8_t mbr[512];
139 mmc_window_start = 0;
140 mmc_window_end = INT_MAX;
141 ret = mmc_read_sectors(IF_MD2(0,) 0, 1, mbr);
142 if(ret != 0)
143 return -100;
144 if(mbr[510] != 0x55 || mbr[511] != 0xAA)
145 return -101; /* invalid MBR */
146 /* sanity check that the first partition is greater than 2Gib */
147 uint8_t *ent = &mbr[446];
148 mmc_window_start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24;
149 mmc_window_end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24) +
150 mmc_window_start;
151 if(ent[4] == 0x53)
152 return -102; /* sigmatel partition */
153 if((mmc_window_end - mmc_window_start) < 4 * 1024 * 1024)
154 return -103; /* partition too small */
155 #endif
74 156
75 return 0; 157 return 0;
76} 158}
@@ -81,13 +163,49 @@ int mmc_num_drives(int first_drive)
81 return 1; 163 return 1;
82} 164}
83 165
84int mmc_read_sectors(IF_MD2(int drive,) unsigned long start, int count, void* buf) 166#ifdef STORAGE_GET_INFO
167void mmc_get_info(IF_MD2(int drive,) struct storage_info *info)
168{
169#ifdef HAVE_MULTIDRIVE
170 (void) drive;
171#endif
172 info->sector_size = 512;
173 info->num_sectors = 0xECC000 - 0x0001ac00;
174 info->vendor = "Rockbox";
175 info->product = "Internal Storage";
176 info->revision = "0.00";
177}
178#endif
179
180int mmc_read_sectors(IF_MD2(int drive,) unsigned long start, int count, void *buf)
85{ 181{
86 IF_MD((void) drive); 182 IF_MD((void) drive);
87 (void) start; 183 /* check window */
88 (void) count; 184 start += mmc_window_start;
89 (void) buf; 185 if((start + count) > mmc_window_end)
90 return -1; 186 return -201;
187 /* get mutex (needed because we done multiple commands for count > 0 */
188 mutex_lock(&mmc_mutex);
189 int ret = 0;
190 uint32_t resp;
191
192 if(count == 1)
193 {
194 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 17, start, SSP_SHORT_RESP, buf,
195 count, false, true, &resp);
196 }
197 else
198 {
199 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 23, count, SSP_SHORT_RESP, NULL,
200 0, false, false, &resp);
201 if(ret == 0)
202 ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 18, start, SSP_SHORT_RESP, buf,
203 count, false, true, &resp);
204 }
205
206 mutex_unlock(&mmc_mutex);
207
208 return ret;
91} 209}
92 210
93int mmc_write_sectors(IF_MD2(int drive,) unsigned long start, int count, const void* buf) 211int mmc_write_sectors(IF_MD2(int drive,) unsigned long start, int count, const void* buf)
diff --git a/firmware/target/arm/imx233/sd-imx233.c b/firmware/target/arm/imx233/sd-imx233.c
index 6f30c7a3c6..ccd8bf35c1 100644
--- a/firmware/target/arm/imx233/sd-imx233.c
+++ b/firmware/target/arm/imx233/sd-imx233.c
@@ -25,7 +25,7 @@
25 25
26int sd_init(void) 26int sd_init(void)
27{ 27{
28 return -1; 28 return 0;
29} 29}
30 30
31int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, 31int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
diff --git a/firmware/target/arm/imx233/ssp-imx233.c b/firmware/target/arm/imx233/ssp-imx233.c
index c6be869ce6..22824964f3 100644
--- a/firmware/target/arm/imx233/ssp-imx233.c
+++ b/firmware/target/arm/imx233/ssp-imx233.c
@@ -42,6 +42,8 @@ static int ssp_in_use = 0;
42static struct mutex ssp_mutex[2]; 42static struct mutex ssp_mutex[2];
43static struct semaphore ssp_sema[2]; 43static struct semaphore ssp_sema[2];
44static struct ssp_dma_command_t ssp_dma_cmd[2]; 44static struct ssp_dma_command_t ssp_dma_cmd[2];
45static uint32_t ssp_bus_width[2];
46static unsigned ssp_log_block_size[2];
45 47
46void INT_SSP(int ssp) 48void INT_SSP(int ssp)
47{ 49{
@@ -84,6 +86,7 @@ void imx233_ssp_init(void)
84 semaphore_init(&ssp_sema[1], 1, 0); 86 semaphore_init(&ssp_sema[1], 1, 0);
85 mutex_init(&ssp_mutex[0]); 87 mutex_init(&ssp_mutex[0]);
86 mutex_init(&ssp_mutex[1]); 88 mutex_init(&ssp_mutex[1]);
89 ssp_bus_width[0] = ssp_bus_width[1] = HW_SSP_CTRL0__BUS_WIDTH__ONE_BIT;
87} 90}
88 91
89void imx233_ssp_start(int ssp) 92void imx233_ssp_start(int ssp)
@@ -96,11 +99,12 @@ void imx233_ssp_start(int ssp)
96 /* If first block to start, start SSP clock */ 99 /* If first block to start, start SSP clock */
97 if(ssp_in_use == 0) 100 if(ssp_in_use == 0)
98 { 101 {
102 /** 2.3.1: the clk_ssp maximum frequency is 102.858 MHz */
99 /* fracdiv = 18 => clk_io = pll = 480Mhz 103 /* fracdiv = 18 => clk_io = pll = 480Mhz
100 * intdiv = 4 => clk_ssp = 120Mhz */ 104 * intdiv = 5 => clk_ssp = 96Mhz */
101 imx233_set_fractional_divisor(CLK_IO, 18); 105 imx233_set_fractional_divisor(CLK_IO, 18);
102 imx233_enable_clock(CLK_SSP, false); 106 imx233_enable_clock(CLK_SSP, false);
103 imx233_set_clock_divisor(CLK_SSP, 4); 107 imx233_set_clock_divisor(CLK_SSP, 5);
104 imx233_set_bypass_pll(CLK_SSP, false); /* use IO */ 108 imx233_set_bypass_pll(CLK_SSP, false); /* use IO */
105 imx233_enable_clock(CLK_SSP, true); 109 imx233_enable_clock(CLK_SSP, true);
106 } 110 }
@@ -127,18 +131,9 @@ void imx233_ssp_softreset(int ssp)
127 imx233_reset_block(&HW_SSP_CTRL0(ssp)); 131 imx233_reset_block(&HW_SSP_CTRL0(ssp));
128} 132}
129 133
130void imx233_ssp_set_timings(int ssp, int divide, int rate) 134void imx233_ssp_set_timings(int ssp, int divide, int rate, int timeout)
131{ 135{
132 __REG_CLR(HW_SSP_TIMING(ssp)) = 136 HW_SSP_TIMING(ssp) = divide << HW_SSP_TIMING__CLOCK_DIVIDE_BP | rate |
133 HW_SSP_TIMING__CLOCK_DIVIDE_BM | HW_SSP_TIMING__CLOCK_RATE_BM;
134 __REG_SET(HW_SSP_TIMING(ssp)) =
135 divide << HW_SSP_TIMING__CLOCK_DIVIDE_BP | rate;
136}
137
138void imx233_ssp_set_timeout(int ssp, int timeout)
139{
140 __REG_CLR(HW_SSP_TIMING(ssp)) = HW_SSP_TIMING__CLOCK_TIMEOUT_BM;
141 __REG_SET(HW_SSP_TIMING(ssp)) =
142 timeout << HW_SSP_TIMING__CLOCK_TIMEOUT_BP; 137 timeout << HW_SSP_TIMING__CLOCK_TIMEOUT_BP;
143} 138}
144 139
@@ -238,22 +233,43 @@ void imx233_ssp_set_mode(int ssp, unsigned mode)
238 } 233 }
239} 234}
240 235
241enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_t cmd_arg, 236void imx233_ssp_set_bus_width(int ssp, unsigned width)
242 enum imx233_ssp_resp_t resp, void *buffer, int xfer_size, bool read, uint32_t *resp_ptr) 237{
238 switch(width)
239 {
240 case 1: ssp_bus_width[ssp - 1] = HW_SSP_CTRL0__BUS_WIDTH__ONE_BIT; break;
241 case 4: ssp_bus_width[ssp - 1] = HW_SSP_CTRL0__BUS_WIDTH__FOUR_BIT; break;
242 case 8: ssp_bus_width[ssp - 1] = HW_SSP_CTRL0__BUS_WIDTH__EIGHT_BIT; break;
243 }
244}
245
246void imx233_ssp_set_block_size(int ssp, unsigned log_block_size)
247{
248 ssp_log_block_size[ssp - 1] = log_block_size;
249}
250
251enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd,
252 uint32_t cmd_arg, enum imx233_ssp_resp_t resp, void *buffer, unsigned block_count,
253 bool wait4irq, bool read, uint32_t *resp_ptr)
243{ 254{
244 mutex_lock(&ssp_mutex[ssp - 1]); 255 mutex_lock(&ssp_mutex[ssp - 1]);
245 /* Enable all interrupts */ 256 /* Enable all interrupts */
246 imx233_enable_interrupt(INT_SRC_SSP_DMA(ssp), true); 257 imx233_enable_interrupt(INT_SRC_SSP_DMA(ssp), true);
247 imx233_dma_enable_channel_interrupt(APB_SSP(ssp), true); 258 imx233_dma_enable_channel_interrupt(APB_SSP(ssp), true);
248 /* Assume only one block so ignore block_count and block_size */ 259
249 ssp_dma_cmd[ssp - 1].cmd0 = cmd | HW_SSP_CMD0__APPEND_8CYC; 260 unsigned xfer_size = block_count * (1 << ssp_log_block_size[ssp - 1]);
261
262 ssp_dma_cmd[ssp - 1].cmd0 = cmd | HW_SSP_CMD0__APPEND_8CYC |
263 ssp_log_block_size[ssp - 1] << HW_SSP_CMD0__BLOCK_SIZE_BP |
264 (block_count - 1) << HW_SSP_CMD0__BLOCK_COUNT_BP;
250 ssp_dma_cmd[ssp - 1].cmd1 = cmd_arg; 265 ssp_dma_cmd[ssp - 1].cmd1 = cmd_arg;
251 /* setup all flags and run */ 266 /* setup all flags and run */
252 ssp_dma_cmd[ssp - 1].ctrl0 = xfer_size | HW_SSP_CTRL0__ENABLE | 267 ssp_dma_cmd[ssp - 1].ctrl0 = xfer_size | HW_SSP_CTRL0__ENABLE |
253 HW_SSP_CTRL0__IGNORE_CRC | 268 (buffer ? 0 : HW_SSP_CTRL0__IGNORE_CRC) |
254 (resp != SSP_NO_RESP ? HW_SSP_CTRL0__GET_RESP | HW_SSP_CTRL0__WAIT_FOR_IRQ : 0) | 269 (wait4irq ? HW_SSP_CTRL0__WAIT_FOR_IRQ : 0) |
270 (resp != SSP_NO_RESP ? HW_SSP_CTRL0__GET_RESP : 0) |
255 (resp == SSP_LONG_RESP ? HW_SSP_CTRL0__LONG_RESP : 0) | 271 (resp == SSP_LONG_RESP ? HW_SSP_CTRL0__LONG_RESP : 0) |
256 HW_SSP_CTRL0__BUS_WIDTH__ONE_BIT << HW_SSP_CTRL0__BUS_WIDTH_BP | 272 (ssp_bus_width[ssp - 1] << HW_SSP_CTRL0__BUS_WIDTH_BP) |
257 (buffer ? HW_SSP_CTRL0__DATA_XFER : 0) | 273 (buffer ? HW_SSP_CTRL0__DATA_XFER : 0) |
258 (read ? HW_SSP_CTRL0__READ : 0); 274 (read ? HW_SSP_CTRL0__READ : 0);
259 /* setup the dma parameters */ 275 /* setup the dma parameters */
@@ -263,10 +279,11 @@ enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_
263 (buffer == NULL ? HW_APB_CHx_CMD__COMMAND__NO_XFER : 279 (buffer == NULL ? HW_APB_CHx_CMD__COMMAND__NO_XFER :
264 read ? HW_APB_CHx_CMD__COMMAND__WRITE : HW_APB_CHx_CMD__COMMAND__READ) | 280 read ? HW_APB_CHx_CMD__COMMAND__WRITE : HW_APB_CHx_CMD__COMMAND__READ) |
265 HW_APB_CHx_CMD__IRQONCMPLT | HW_APB_CHx_CMD__SEMAPHORE | 281 HW_APB_CHx_CMD__IRQONCMPLT | HW_APB_CHx_CMD__SEMAPHORE |
266 HW_APB_CHx_CMD__WAIT4ENDCMD | HW_APB_CHx_CMD__HALTONTERMINATE | 282 HW_APB_CHx_CMD__WAIT4ENDCMD |
267 (3 << HW_APB_CHx_CMD__CMDWORDS_BP) | 283 (3 << HW_APB_CHx_CMD__CMDWORDS_BP) |
268 (xfer_size << HW_APB_CHx_CMD__XFER_COUNT_BP); 284 (xfer_size << HW_APB_CHx_CMD__XFER_COUNT_BP);
269 285
286 imx233_dma_reset_channel(APB_SSP(ssp));
270 imx233_dma_start_command(APB_SSP(ssp), &ssp_dma_cmd[ssp - 1].dma); 287 imx233_dma_start_command(APB_SSP(ssp), &ssp_dma_cmd[ssp - 1].dma);
271 288
272 /* the SSP hardware already has a timeout but we never know; 1 sec is a maximum 289 /* the SSP hardware already has a timeout but we never know; 1 sec is a maximum
@@ -283,7 +300,7 @@ enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_
283 else 300 else
284 ret = SSP_ERROR; 301 ret = SSP_ERROR;
285 302
286 if(ret == SSP_SUCCESS && resp_ptr != NULL) 303 if(resp_ptr != NULL)
287 { 304 {
288 if(resp != SSP_NO_RESP) 305 if(resp != SSP_NO_RESP)
289 *resp_ptr++ = HW_SSP_SDRESP0(ssp); 306 *resp_ptr++ = HW_SSP_SDRESP0(ssp);
diff --git a/firmware/target/arm/imx233/ssp-imx233.h b/firmware/target/arm/imx233/ssp-imx233.h
index e9bdf62b27..c7c891ec0b 100644
--- a/firmware/target/arm/imx233/ssp-imx233.h
+++ b/firmware/target/arm/imx233/ssp-imx233.h
@@ -67,7 +67,7 @@
67#define HW_SSP_CMD0__BLOCK_SIZE_BM (0xf << 16) 67#define HW_SSP_CMD0__BLOCK_SIZE_BM (0xf << 16)
68#define HW_SSP_CMD0__BLOCK_SIZE_BP 16 68#define HW_SSP_CMD0__BLOCK_SIZE_BP 16
69#define HW_SSP_CMD0__BLOCK_COUNT_BM (0xff << 8) 69#define HW_SSP_CMD0__BLOCK_COUNT_BM (0xff << 8)
70#define HW_SSP_CMD0__BLOCK_COUNT_BP 16 70#define HW_SSP_CMD0__BLOCK_COUNT_BP 8
71#define HW_SSP_CMD0__CMD_BM 0xff 71#define HW_SSP_CMD0__CMD_BM 0xff
72 72
73#define HW_SSP_CMD1(ssp) (*(volatile uint32_t *)(HW_SSP_BASE(ssp) + 0x20)) 73#define HW_SSP_CMD1(ssp) (*(volatile uint32_t *)(HW_SSP_BASE(ssp) + 0x20))
@@ -147,12 +147,15 @@ void imx233_ssp_start(int ssp);
147void imx233_ssp_stop(int ssp); 147void imx233_ssp_stop(int ssp);
148/* only softreset between start and stop or it might hang ! */ 148/* only softreset between start and stop or it might hang ! */
149void imx233_ssp_softreset(int ssp); 149void imx233_ssp_softreset(int ssp);
150void imx233_ssp_set_timings(int ssp, int divide, int rate); 150void imx233_ssp_set_timings(int ssp, int divide, int rate, int timeout);
151void imx233_ssp_set_timeout(int ssp, int timeout);
152void imx233_ssp_set_mode(int ssp, unsigned mode); 151void imx233_ssp_set_mode(int ssp, unsigned mode);
152void imx233_ssp_set_bus_width(int ssp, unsigned width);
153/* block_size uses the SSP format so it's actually the log_2 of the block_size */
154void imx233_ssp_set_block_size(int ssp, unsigned log_block_size);
153/* SD/MMC facilities */ 155/* SD/MMC facilities */
154enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_t cmd_arg, 156enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd,
155 enum imx233_ssp_resp_t resp, void *buffer, int xfer_size, bool read, uint32_t *resp_ptr); 157 uint32_t cmd_arg, enum imx233_ssp_resp_t resp, void *buffer, unsigned block_count,
158 bool wait4irq, bool read, uint32_t *resp_ptr);
156void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width, 159void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width,
157 unsigned drive_strength); 160 unsigned drive_strength);
158/* SD/MMC requires that the card be provided the clock during an init sequence of 161/* SD/MMC requires that the card be provided the clock during an init sequence of
diff --git a/firmware/target/arm/imx233/system-imx233.c b/firmware/target/arm/imx233/system-imx233.c
index 9c843c48c1..6114ecca08 100644
--- a/firmware/target/arm/imx233/system-imx233.c
+++ b/firmware/target/arm/imx233/system-imx233.c
@@ -31,6 +31,7 @@
31#include "ssp-imx233.h" 31#include "ssp-imx233.h"
32#include "lcd.h" 32#include "lcd.h"
33#include "backlight-target.h" 33#include "backlight-target.h"
34#include "button-target.h"
34 35
35#define default_interrupt(name) \ 36#define default_interrupt(name) \
36 extern __attribute__((weak, alias("UIRQ"))) void name(void) 37 extern __attribute__((weak, alias("UIRQ"))) void name(void)
@@ -104,7 +105,13 @@ void system_reboot(void)
104 105
105void system_exception_wait(void) 106void system_exception_wait(void)
106{ 107{
107 /* what is this supposed to do ? */ 108 /* make sure lcd and backlight are on */
109 _backlight_on();
110 _backlight_set_brightness(100);
111 /* wait until button release (if a button is pressed) */
112 while(button_read_device());
113 /* then wait until next button press */
114 while(!button_read_device());
108} 115}
109 116
110void imx233_enable_interrupt(int src, bool enable) 117void imx233_enable_interrupt(int src, bool enable)
@@ -177,3 +184,23 @@ void udelay(unsigned us)
177 while(!imx233_us_elapsed(ref, us)); 184 while(!imx233_us_elapsed(ref, us));
178} 185}
179 186
187#ifdef HAVE_ADJUSTABLE_CPU_FREQ
188void set_cpu_frequency(long frequency)
189{
190 switch(frequency)
191 {
192 case IMX233_CPUFREQ_454_MHz:
193 /* clk_h@clk_p/3 */
194 imx233_set_clock_divisor(CLK_AHB, 3);
195 /* clk_p@ref_cpu/1*18/19 */
196 imx233_set_fractional_divisor(CLK_CPU, 19);
197 imx233_set_clock_divisor(CLK_CPU, 1);
198 /* ref_cpu@480 MHz
199 * clk_p@454.74 MHz
200 * clk_h@151.58 MHz */
201 break;
202 default:
203 break;
204 }
205}
206#endif
diff --git a/firmware/target/arm/imx233/system-target.h b/firmware/target/arm/imx233/system-target.h
index 163eacb41f..0f7bde4896 100644
--- a/firmware/target/arm/imx233/system-target.h
+++ b/firmware/target/arm/imx233/system-target.h
@@ -31,10 +31,35 @@
31#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) 31#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
32 32
33#define HW_POWER_BASE 0x80044000 33#define HW_POWER_BASE 0x80044000
34
35#define HW_POWER_CTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x0))
36
37#define HW_POWER_5VCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x10))
38
39#define HW_POWER_MINPWR (*(volatile uint32_t *)(HW_POWER_BASE + 0x20))
40
41#define HW_POWER_CHARGE (*(volatile uint32_t *)(HW_POWER_BASE + 0x30))
42
43#define HW_POWER_VDDDCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x40))
44#define HW_POWER_VDDDCTRL__TRG_BP 0
45#define HW_POWER_VDDDCTRL__TRG_BM 0x1f
46#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */
47#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */
48
49#define HW_POWER_VDDACTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x50))
50
51#define HW_POWER_VDDIOCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x60))
52
53#define HW_POWER_VDDMEMCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x70))
54
55#define HW_POWER_MISC (*(volatile uint32_t *)(HW_POWER_BASE + 0x90))
56
34#define HW_POWER_STS (*(volatile uint32_t *)(HW_POWER_BASE + 0xc0)) 57#define HW_POWER_STS (*(volatile uint32_t *)(HW_POWER_BASE + 0xc0))
35#define HW_POWER_STS__PSWITCH_BP 20 58#define HW_POWER_STS__PSWITCH_BP 20
36#define HW_POWER_STS__PSWITCH_BM (3 << 20) 59#define HW_POWER_STS__PSWITCH_BM (3 << 20)
37 60
61#define HW_POWER_BATTMONITOR (*(volatile uint32_t *)(HW_POWER_BASE + 0xe0))
62
38#define HW_POWER_RESET (*(volatile uint32_t *)(HW_POWER_BASE + 0x100)) 63#define HW_POWER_RESET (*(volatile uint32_t *)(HW_POWER_BASE + 0x100))
39#define HW_POWER_RESET__UNLOCK 0x3E770000 64#define HW_POWER_RESET__UNLOCK 0x3E770000
40#define HW_POWER_RESET__PWD 0x1 65#define HW_POWER_RESET__PWD 0x1
@@ -67,6 +92,22 @@
67#define INT_SRC_LCDIF_ERROR 46 92#define INT_SRC_LCDIF_ERROR 46
68#define INT_SRC_NR_SOURCES 66 93#define INT_SRC_NR_SOURCES 66
69 94
95/**
96 * Absolute maximum CPU speed: 454.74 MHz
97 * Intermediate CPU speeds: 392.73 MHz, 360MHz, 261.82 MHz, 64 MHz
98 * Absolute minimum CPU speed: 24 MHz */
99#define IMX233_CPUFREQ_454_MHz 454740000
100#define IMX233_CPUFREQ_392_MHz 392730000
101#define IMX233_CPUFREQ_360_MHz 360000000
102#define IMX233_CPUFREQ_261_MHz 261820000
103#define IMX233_CPUFREQ_64_MHz 64000000
104#define IMX233_CPUFREQ_24_MHz 24000000
105
106#define CPUFREQ_DEFAULT IMX233_CPUFREQ_454_MHz
107#define CPUFREQ_NORMAL IMX233_CPUFREQ_454_MHz
108#define CPUFREQ_MAX IMX233_CPUFREQ_454_MHz
109#define CPUFREQ_SLEEP IMX233_CPUFREQ_454_MHz
110
70void imx233_enable_interrupt(int src, bool enable); 111void imx233_enable_interrupt(int src, bool enable);
71void imx233_softirq(int src, bool enable); 112void imx233_softirq(int src, bool enable);
72void udelay(unsigned us); 113void udelay(unsigned us);
diff --git a/firmware/target/arm/imx233/usb-imx233.c b/firmware/target/arm/imx233/usb-imx233.c
index 83e50839b4..e3b540fd1e 100644
--- a/firmware/target/arm/imx233/usb-imx233.c
+++ b/firmware/target/arm/imx233/usb-imx233.c
@@ -48,7 +48,6 @@ void usb_drv_int_enable(bool enable)
48 48
49void INT_USB_CTRL(void) 49void INT_USB_CTRL(void)
50{ 50{
51 printf("usb int");
52 usb_drv_int(); 51 usb_drv_int();
53} 52}
54 53