Skip to content

Commit d49d254

Browse files
committed
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 dfff383 commit d49d254

File tree

1 file changed

+141
-27
lines changed

1 file changed

+141
-27
lines changed

drivers/mmc/host/bcm2835.c

Lines changed: 141 additions & 27 deletions
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,24 @@ 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+
if (host->overclock) {
614+
if ((mrq->cmd && mrq->cmd->error &&
615+
(mrq->cmd->opcode != MMC_SEND_STATUS)) ||
616+
(mrq->data && mrq->data->error) ||
617+
(mrq->stop && mrq->stop->error) ||
618+
(mrq->sbc && mrq->sbc->error)) {
619+
host->overclock_50--;
620+
dev_warn(&host->pdev->dev,
621+
"reducing overclock due to errors\n");
622+
host->reset_clock = 1;
623+
mrq->cmd->error = -ETIMEDOUT;
624+
mrq->cmd->retries = 1;
625+
}
626+
}
627+
598628
host->mrq = NULL;
599629
host->cmd = NULL;
600630
host->data = NULL;
@@ -1091,8 +1121,13 @@ static void bcm2835_dma_complete_work(struct work_struct *work)
10911121
static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
10921122
{
10931123
struct mmc_host *mmc = mmc_from_priv(host);
1124+
const unsigned int input_clock = clock;
1125+
const unsigned int MHZ = 1000000;
10941126
int div;
10951127

1128+
if (host->overclock_50 && (clock == 50*MHZ))
1129+
clock = host->overclock_50 * MHZ + (MHZ - 1);
1130+
10961131
/* The SDCDIV register has 11 bits, and holds (div - 2). But
10971132
* in data mode the max is 50MHz wihout a minimum, and only
10981133
* the bottom 3 bits are used. Since the switch over is
@@ -1114,38 +1149,76 @@ static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
11141149
* clock divisor at all times.
11151150
*/
11161151

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-
}
1152+
if (host->fw) {
1153+
u32 msg[3] = { clock, 0, 0 };
11251154

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;
1155+
rpi_firmware_property(host->fw,
1156+
RPI_FIRMWARE_SET_SDHOST_CLOCK,
1157+
&msg, sizeof(msg));
11321158

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

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

11391187
/* Calibrate some delays */
11401188

11411189
host->ns_per_fifo_word = (1000000000 / clock) *
11421190
((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
11431191

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

11471216
/* Set the timeout to 500ms */
1148-
writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT);
1217+
writel(clock / 2, host->ioaddr + SDTOUT);
1218+
1219+
mmc->actual_clock = clock;
1220+
host->clock = input_clock;
1221+
host->reset_clock = 0;
11491222
}
11501223

11511224
static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -1175,6 +1248,9 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
11751248
return;
11761249
}
11771250

1251+
if (host->reset_clock)
1252+
bcm2835_set_clock(host, host->clock);
1253+
11781254
mutex_lock(&host->mutex);
11791255

11801256
WARN_ON(host->mrq);
@@ -1198,7 +1274,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
11981274
return;
11991275
}
12001276

1201-
if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
1277+
if (host->use_dma && mrq->data && (mrq->data->blocks > host->pio_limit))
12021278
bcm2835_prepare_dma(host, mrq->data);
12031279

12041280
host->use_sbc = !!mrq->sbc && host->mrq->data &&
@@ -1333,8 +1409,8 @@ static int bcm2835_add_host(struct bcm2835_host *host)
13331409
}
13341410

13351411
pio_limit_string[0] = '\0';
1336-
if (host->use_dma && (PIO_THRESHOLD > 0))
1337-
sprintf(pio_limit_string, " (>%d)", PIO_THRESHOLD);
1412+
if (host->use_dma && (host->pio_limit > 0))
1413+
sprintf(pio_limit_string, " (>%d)", host->pio_limit);
13381414
dev_info(dev, "loaded - DMA %s%s\n",
13391415
host->use_dma ? "enabled" : "disabled", pio_limit_string);
13401416

@@ -1344,10 +1420,13 @@ static int bcm2835_add_host(struct bcm2835_host *host)
13441420
static int bcm2835_probe(struct platform_device *pdev)
13451421
{
13461422
struct device *dev = &pdev->dev;
1347-
struct clk *clk;
1423+
struct device_node *node = dev->of_node;
13481424
struct bcm2835_host *host;
1425+
struct rpi_firmware *fw;
13491426
struct resource *iomem;
1427+
bool allow_dma = true;
13501428
struct mmc_host *mmc;
1429+
struct clk *clk;
13511430
int ret;
13521431

13531432
dev_dbg(dev, "%s\n", __func__);
@@ -1367,6 +1446,23 @@ static int bcm2835_probe(struct platform_device *pdev)
13671446
}
13681447

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

13711467
host->dma_chan = NULL;
13721468
host->dma_desc = NULL;
@@ -1389,6 +1485,24 @@ static int bcm2835_probe(struct platform_device *pdev)
13891485
goto err;
13901486
}
13911487

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

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

0 commit comments

Comments
 (0)