summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVencislav Atanasov <user890104@freemyipod.org>2024-12-06 23:37:49 +0200
committerVencislav Atanasov <user890104@freemyipod.org>2024-12-06 23:59:27 +0200
commit2669548bcd68ff635f74493782c080d3c735194b (patch)
treed6c934d88693c01d025a212cbebbc99ed3618107
parentb240f01059386e883949de558e2cbdf14de887fc (diff)
downloadrockbox-2669548bcd.tar.gz
rockbox-2669548bcd.zip
S5L8720: Add support for Timers, SPI, CPUFREQ and USB
This also includes a small SPI driver rework for ipod6g. Only the NOR flash currently uses SPI. Tested on target using View SysCfg in Debug menu. This is a part of the large iPod Nano 4G and iPod Touch 2G support patch. Credit: Cástor Muñoz <cmvidal@gmail.com> Change-Id: If2b91c1088034dd606abc6dd0b6ad73dea0152a4
-rw-r--r--firmware/target/arm/s5l8702/kernel-s5l8702.c16
-rw-r--r--firmware/target/arm/s5l8702/spi-s5l8702.c50
-rw-r--r--firmware/target/arm/s5l8702/system-target.h7
-rw-r--r--firmware/target/arm/s5l8702/usb-s5l8702.c6
4 files changed, 76 insertions, 3 deletions
diff --git a/firmware/target/arm/s5l8702/kernel-s5l8702.c b/firmware/target/arm/s5l8702/kernel-s5l8702.c
index 6a70981c93..0a5413af73 100644
--- a/firmware/target/arm/s5l8702/kernel-s5l8702.c
+++ b/firmware/target/arm/s5l8702/kernel-s5l8702.c
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id: kernel-s5l8700.c 28795 2010-12-11 17:52:52Z Buschel $
*
- * Copyright © 2009 Bertrik Sikken
+ * Copyright © 2009 Bertrik Sikken
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,6 +39,7 @@ void tick_start(unsigned int interval_in_ms)
{
int cycles = 10 * interval_in_ms;
+#if CONFIG_CPU == S5L8702
/* configure timer for 10 kHz (12 MHz / 16 / 75) */
TBCMD = (1 << 1); /* TB_CLR */
TBPRE = 75 - 1; /* prescaler */
@@ -50,5 +51,18 @@ void tick_start(unsigned int interval_in_ms)
(0 << 4); /* TB_MODE_SEL = interval mode */
TBDATA0 = cycles; /* set interval period */
TBCMD = (1 << 0); /* TB_EN */
+#elif CONFIG_CPU == S5L8720
+ /* configure timer for 10 kHz (24 MHz / 16 / 150) */
+ TBCMD = (1 << 1); /* TB_CLR */
+ TBPRE = 150 - 1; /* prescaler */
+ TBCON = (0 << 13) | /* TB_INT1_EN */
+ (1 << 12) | /* TB_INT0_EN */
+ (0 << 11) | /* TB_START */
+ (2 << 8) | /* TB_CS = ECLK / 16 */
+ (1 << 6) | /* select ECLK (24 MHz) */
+ (0 << 4); /* TB_MODE_SEL = interval mode */
+ TBDATA0 = cycles; /* set interval period */
+ TBCMD = (1 << 0); /* TB_EN */
+#endif
}
diff --git a/firmware/target/arm/s5l8702/spi-s5l8702.c b/firmware/target/arm/s5l8702/spi-s5l8702.c
index 4c0a409c67..5178da0342 100644
--- a/firmware/target/arm/s5l8702/spi-s5l8702.c
+++ b/firmware/target/arm/s5l8702/spi-s5l8702.c
@@ -47,6 +47,7 @@ void spi_init(int port, bool state)
case 0:
PCON0 = (PCON0 & ~0xffff) | val;
break;
+#if CONFIG_CPU == S5L8702
case 1:
PCON6 = (PCON6 & ~0xffff0000) | (val << 16);
break;
@@ -54,6 +55,15 @@ void spi_init(int port, bool state)
PCON14 = (PCON14 & ~0xff000000) | (val << 24);
PCON15 = (PCON15 & ~0xff) | (val >> 8);
break;
+#elif CONFIG_CPU == S5L8720
+ case 1:
+ PCON4 = (PCON4 & ~0xff000000) | (val << 24);
+ PCON5 = (PCON5 & ~0xff) | (val >> 8);
+ break;
+ case 2:
+ /* unknown */
+ break;
+#endif
}
}
@@ -67,19 +77,33 @@ void spi_ce(int port, bool state)
switch (port)
{
case 0: GPIOCMD = 0x0000e | level; break;
+#if CONFIG_CPU == S5L8702
case 1: GPIOCMD = 0x6040e | level; break;
case 2: GPIOCMD = 0xe060e | level; break;
+#elif CONFIG_CPU == S5L8720
+ case 1: GPIOCMD = 0x4060e | level; break;
+ case 2: /* unknown */ break;
+#endif
}
}
void spi_prepare(int port)
{
clockgate_enable(SPICLKGATE(port), true);
+#if CONFIG_CPU == S5L8720
+ clockgate_enable(SPICLKGATE_2(port), true);
+#endif
SPISTATUS(port) = 0xf;
SPICTRL(port) |= 0xc;
SPICLKDIV(port) = clkdiv[port];
SPIPIN(port) = 6;
+#if CONFIG_CPU == S5L8702
SPISETUP(port) = 0x10618;
+#elif CONFIG_CPU == S5L8720
+ SPIUNK40(port) = 0xffffffff;
+ SPIUNK3C(port) = 0xffffffff;
+ SPISETUP(port) = 0x40618;
+#endif
SPICTRL(port) |= 0xc;
SPICTRL(port) = 1;
}
@@ -87,25 +111,47 @@ void spi_prepare(int port)
void spi_release(int port)
{
clockgate_enable(SPICLKGATE(port), false);
+#if CONFIG_CPU == S5L8720
+ clockgate_enable(SPICLKGATE_2(port), false);
+#endif
+}
+
+static inline void spi_wait_ready(int port)
+{
+#if CONFIG_CPU == S5L8702
+ while (!(SPISTATUS(port) & 0x3e00));
+#elif CONFIG_CPU == S5L8720
+ while (!(SPISTATUS(port) & 0xf800));
+#endif
}
uint32_t spi_write(int port, uint32_t data)
{
+#if CONFIG_CPU == S5L8702
SPIRXLIMIT(port) = 1;
while ((SPISTATUS(port) & 0x1f0) == 0x100);
+#elif CONFIG_CPU == S5L8720
+ SPIUNK4C(port) = 1;
+ SPIRXLIMIT(port) = 1;
+ // TODO: Wouldn't this be 0x7c0? so that the rule of <<2 is fulfilled in this register?
+ while ((SPISTATUS(port) & 0x7f0) == 0x400);
+#endif
SPITXDATA(port) = data;
- while (!(SPISTATUS(port) & 0x3e00));
+ spi_wait_ready(port);
return SPIRXDATA(port);
}
void spi_read(int port, uint32_t size, void* buf)
{
uint8_t* buffer = (uint8_t*)buf;
+#if CONFIG_CPU == S5L8720
+ SPIUNK4C(port) = size;
+#endif
SPIRXLIMIT(port) = size;
SPISETUP(port) |= 1;
while (size--)
{
- while (!(SPISTATUS(port) & 0x3e00));
+ spi_wait_ready(port);
*buffer++ = SPIRXDATA(port);
}
SPISETUP(port) &= ~1;
diff --git a/firmware/target/arm/s5l8702/system-target.h b/firmware/target/arm/s5l8702/system-target.h
index d3db7476ee..65aba53a91 100644
--- a/firmware/target/arm/s5l8702/system-target.h
+++ b/firmware/target/arm/s5l8702/system-target.h
@@ -25,9 +25,16 @@
#include "mmu-arm.h"
#define CPUFREQ_SLEEP 32768
+
+#if (CONFIG_CPU == S5L8702)
#define CPUFREQ_MAX 216000000
#define CPUFREQ_DEFAULT 54000000
#define CPUFREQ_NORMAL 54000000
+#elif (CONFIG_CPU == S5L8720)
+#define CPUFREQ_MAX 266000000
+#define CPUFREQ_DEFAULT 133000000
+#define CPUFREQ_NORMAL 133000000
+#endif
#define STORAGE_WANTS_ALIGN
diff --git a/firmware/target/arm/s5l8702/usb-s5l8702.c b/firmware/target/arm/s5l8702/usb-s5l8702.c
index 9e031a049f..2fa5033ef6 100644
--- a/firmware/target/arm/s5l8702/usb-s5l8702.c
+++ b/firmware/target/arm/s5l8702/usb-s5l8702.c
@@ -69,10 +69,16 @@ void usb_dw_target_enable_clocks()
void usb_dw_target_disable_clocks()
{
+#if (CONFIG_CPU == S5L8702)
OPHYPWR = 0xf; /* PHY: Power down */
udelay(10);
ORSTCON = 7; /* PHY: Assert Software Reset */
udelay(10);
+#elif (CONFIG_CPU == S5L8720)
+ OPHYPWR = 0x1f; /* PHY: Power down */
+ ORSTCON = 1; /* PHY: Assert Software Reset */
+ udelay(1000);
+#endif
clockgate_enable(CLOCKGATE_USBOTG, false);
clockgate_enable(CLOCKGATE_USBPHY, false);