Skip to content

Commit 005644c

Browse files
pelwellpopcornmix
authored andcommitted
mmc: bcm2835: Add downstream overclocking support
The principal differences between the downstream SDHOST driver and the version accepted upstream driver are that the upstream version loses the overclock support and DMA configuration via DT, but gains some tidying up (and maintenance by the upstream devs). Add the missing features (with the exception of the low-overhead logging) as a patch to the upstream driver. Signed-off-by: Phil Elwell <[email protected]>
1 parent 8534f69 commit 005644c

File tree

1 file changed

+144
-27
lines changed

1 file changed

+144
-27
lines changed

drivers/mmc/host/bcm2835.c

+144-27
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
#include <linux/mmc/mmc.h>
4949
#include <linux/mmc/sd.h>
5050

51+
#include <soc/bcm2835/raspberrypi-firmware.h>
52+
5153
#define SDCMD 0x00 /* Command to SD card - 16 R/W */
5254
#define SDARG 0x04 /* Argument to SD card - 32 R/W */
5355
#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
@@ -186,6 +188,14 @@ struct bcm2835_host {
186188
struct page *drain_page;
187189
u32 drain_offset;
188190
bool use_dma;
191+
192+
/* Downstream additions */
193+
struct rpi_firmware *fw;
194+
u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */
195+
u32 user_overclock_50; /* User's preferred overclock frequency */
196+
u32 overclock_50; /* Freq to use when 50MHz is requested (MHz) */
197+
u32 overclock; /* Current frequency if overclocked, else zero */
198+
bool reset_clock:1; /* Reset the clock for the next request */
189199
};
190200

191201
static void bcm2835_dumpcmd(struct bcm2835_host *host, struct mmc_command *cmd,
@@ -240,8 +250,11 @@ static void bcm2835_dumpregs(struct bcm2835_host *host)
240250

241251
static void bcm2835_reset_internal(struct bcm2835_host *host)
242252
{
253+
u32 cdiv = host->cdiv;
243254
u32 temp;
244255

256+
if (!cdiv)
257+
cdiv = readl(host->ioaddr + SDCDIV);
245258
writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD);
246259
writel(0, host->ioaddr + SDCMD);
247260
writel(0, host->ioaddr + SDARG);
@@ -262,9 +275,8 @@ static void bcm2835_reset_internal(struct bcm2835_host *host)
262275
msleep(20);
263276
writel(SDVDD_POWER_ON, host->ioaddr + SDVDD);
264277
msleep(20);
265-
host->clock = 0;
266278
writel(host->hcfg, host->ioaddr + SDHCFG);
267-
writel(host->cdiv, host->ioaddr + SDCDIV);
279+
writel(cdiv, host->ioaddr + SDCDIV);
268280
}
269281

270282
static void bcm2835_reset(struct mmc_host *mmc)
@@ -595,6 +607,25 @@ static void bcm2835_finish_request(struct bcm2835_host *host)
595607

596608
mrq = host->mrq;
597609

610+
/* Drop the overclock after any data corruption, or after any
611+
* error while overclocked. Ignore errors for status commands,
612+
* as they are likely when a card is ejected.
613+
*/
614+
if (host->overclock) {
615+
if ((mrq->cmd && mrq->cmd->error &&
616+
(mrq->cmd->opcode != MMC_SEND_STATUS)) ||
617+
(mrq->data && mrq->data->error) ||
618+
(mrq->stop && mrq->stop->error) ||
619+
(mrq->sbc && mrq->sbc->error)) {
620+
host->overclock_50--;
621+
dev_warn(&host->pdev->dev,
622+
"reducing overclock due to errors\n");
623+
host->reset_clock = 1;
624+
mrq->cmd->error = -ETIMEDOUT;
625+
mrq->cmd->retries = 1;
626+
}
627+
}
628+
598629
host->mrq = NULL;
599630
host->cmd = NULL;
600631
host->data = NULL;
@@ -1091,8 +1122,13 @@ static void bcm2835_dma_complete_work(struct work_struct *work)
10911122
static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
10921123
{
10931124
struct mmc_host *mmc = mmc_from_priv(host);
1125+
const unsigned int input_clock = clock;
1126+
const unsigned int MHZ = 1000000;
10941127
int div;
10951128

1129+
if (host->overclock_50 && (clock == 50*MHZ))
1130+
clock = host->overclock_50 * MHZ + (MHZ - 1);
1131+
10961132
/* The SDCDIV register has 11 bits, and holds (div - 2). But
10971133
* in data mode the max is 50MHz wihout a minimum, and only
10981134
* the bottom 3 bits are used. Since the switch over is
@@ -1114,38 +1150,78 @@ static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
11141150
* clock divisor at all times.
11151151
*/
11161152

1117-
if (clock < 100000) {
1118-
/* Can't stop the clock, but make it as slow as possible
1119-
* to show willing
1120-
*/
1121-
host->cdiv = SDCDIV_MAX_CDIV;
1122-
writel(host->cdiv, host->ioaddr + SDCDIV);
1123-
return;
1124-
}
1153+
if (host->fw) {
1154+
u32 msg[3] = { clock, 0, 0 };
11251155

1126-
div = host->max_clk / clock;
1127-
if (div < 2)
1128-
div = 2;
1129-
if ((host->max_clk / div) > clock)
1130-
div++;
1131-
div -= 2;
1156+
rpi_firmware_property(host->fw,
1157+
RPI_FIRMWARE_SET_SDHOST_CLOCK,
1158+
&msg, sizeof(msg));
11321159

1133-
if (div > SDCDIV_MAX_CDIV)
1134-
div = SDCDIV_MAX_CDIV;
1160+
clock = max(msg[1], msg[2]);
1161+
host->cdiv = 0;
1162+
} else {
1163+
if (clock < 100000) {
1164+
/* Can't stop the clock, but make it as slow as possible
1165+
* to show willing
1166+
*/
1167+
host->cdiv = SDCDIV_MAX_CDIV;
1168+
writel(host->cdiv, host->ioaddr + SDCDIV);
1169+
return;
1170+
}
11351171

1136-
clock = host->max_clk / (div + 2);
1137-
mmc->actual_clock = clock;
1172+
div = host->max_clk / clock;
1173+
if (div < 2)
1174+
div = 2;
1175+
if ((host->max_clk / div) > clock)
1176+
div++;
1177+
div -= 2;
1178+
1179+
if (div > SDCDIV_MAX_CDIV)
1180+
div = SDCDIV_MAX_CDIV;
1181+
1182+
clock = host->max_clk / (div + 2);
1183+
1184+
host->cdiv = div;
1185+
writel(host->cdiv, host->ioaddr + SDCDIV);
1186+
}
11381187

11391188
/* Calibrate some delays */
11401189

11411190
host->ns_per_fifo_word = (1000000000 / clock) *
11421191
((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
11431192

1144-
host->cdiv = div;
1145-
writel(host->cdiv, host->ioaddr + SDCDIV);
1193+
if (input_clock == 50 * MHZ) {
1194+
if (clock > input_clock) {
1195+
/* Save the closest value, to make it easier
1196+
* to reduce in the event of error
1197+
*/
1198+
host->overclock_50 = (clock/MHZ);
1199+
1200+
if (clock != host->overclock) {
1201+
pr_info("%s: overclocking to %dHz\n",
1202+
mmc_hostname(mmc), clock);
1203+
host->overclock = clock;
1204+
}
1205+
} else if (host->overclock) {
1206+
host->overclock = 0;
1207+
if (clock == 50 * MHZ)
1208+
pr_warn("%s: cancelling overclock\n",
1209+
mmc_hostname(mmc));
1210+
}
1211+
} else if (input_clock == 0) {
1212+
/* Reset the preferred overclock when the clock is stopped.
1213+
* This always happens during initialisation.
1214+
*/
1215+
host->overclock_50 = host->user_overclock_50;
1216+
host->overclock = 0;
1217+
}
11461218

11471219
/* Set the timeout to 500ms */
1148-
writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT);
1220+
writel(clock / 2, host->ioaddr + SDTOUT);
1221+
1222+
mmc->actual_clock = clock;
1223+
host->clock = input_clock;
1224+
host->reset_clock = 0;
11491225
}
11501226

11511227
static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -1175,6 +1251,9 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
11751251
return;
11761252
}
11771253

1254+
if (host->reset_clock)
1255+
bcm2835_set_clock(host, host->clock);
1256+
11781257
mutex_lock(&host->mutex);
11791258

11801259
WARN_ON(host->mrq);
@@ -1198,7 +1277,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
11981277
return;
11991278
}
12001279

1201-
if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
1280+
if (host->use_dma && mrq->data && (mrq->data->blocks > host->pio_limit))
12021281
bcm2835_prepare_dma(host, mrq->data);
12031282

12041283
host->use_sbc = !!mrq->sbc && host->mrq->data &&
@@ -1333,8 +1412,8 @@ static int bcm2835_add_host(struct bcm2835_host *host)
13331412
}
13341413

13351414
pio_limit_string[0] = '\0';
1336-
if (host->use_dma && (PIO_THRESHOLD > 0))
1337-
sprintf(pio_limit_string, " (>%d)", PIO_THRESHOLD);
1415+
if (host->use_dma && (host->pio_limit > 0))
1416+
sprintf(pio_limit_string, " (>%d)", host->pio_limit);
13381417
dev_info(dev, "loaded - DMA %s%s\n",
13391418
host->use_dma ? "enabled" : "disabled", pio_limit_string);
13401419

@@ -1344,10 +1423,13 @@ static int bcm2835_add_host(struct bcm2835_host *host)
13441423
static int bcm2835_probe(struct platform_device *pdev)
13451424
{
13461425
struct device *dev = &pdev->dev;
1347-
struct clk *clk;
1426+
struct device_node *node = dev->of_node;
13481427
struct bcm2835_host *host;
1428+
struct rpi_firmware *fw;
13491429
struct resource *iomem;
1430+
bool allow_dma = true;
13501431
struct mmc_host *mmc;
1432+
struct clk *clk;
13511433
int ret;
13521434

13531435
dev_dbg(dev, "%s\n", __func__);
@@ -1367,6 +1449,23 @@ static int bcm2835_probe(struct platform_device *pdev)
13671449
}
13681450

13691451
host->phys_addr = iomem->start;
1452+
host->pio_limit = PIO_THRESHOLD;
1453+
1454+
if (node) {
1455+
/* Read any custom properties */
1456+
of_property_read_u32(node,
1457+
"brcm,overclock-50",
1458+
&host->user_overclock_50);
1459+
of_property_read_u32(node,
1460+
"brcm,pio-limit",
1461+
&host->pio_limit);
1462+
allow_dma =
1463+
!of_property_read_bool(node, "brcm,force-pio");
1464+
1465+
/* Formally recognise the other way of disabling DMA */
1466+
if (host->pio_limit == 0x7fffffff)
1467+
allow_dma = false;
1468+
}
13701469

13711470
host->dma_chan = NULL;
13721471
host->dma_desc = NULL;
@@ -1389,6 +1488,24 @@ static int bcm2835_probe(struct platform_device *pdev)
13891488
goto err;
13901489
}
13911490

1491+
fw = rpi_firmware_get(
1492+
of_parse_phandle(dev->of_node, "firmware", 0));
1493+
if (fw) {
1494+
u32 msg[3];
1495+
1496+
msg[0] = 0;
1497+
msg[1] = ~0;
1498+
msg[2] = ~0;
1499+
1500+
rpi_firmware_property(fw, RPI_FIRMWARE_SET_SDHOST_CLOCK,
1501+
&msg, sizeof(msg));
1502+
1503+
if (msg[1] != ~0)
1504+
host->fw = fw;
1505+
else
1506+
rpi_firmware_put(fw);
1507+
}
1508+
13921509
host->max_clk = clk_get_rate(clk);
13931510

13941511
host->irq = platform_get_irq(pdev, 0);

0 commit comments

Comments
 (0)