Skip to content

Commit 6523d55

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 <phil@raspberrypi.com>
1 parent 021a8ee commit 6523d55

File tree

1 file changed

+143
-26
lines changed

1 file changed

+143
-26
lines changed

drivers/mmc/host/bcm2835.c

Lines changed: 143 additions & 26 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 */
@@ -187,6 +189,14 @@ struct bcm2835_host {
187189
struct page *drain_page;
188190
u32 drain_offset;
189191
bool use_dma;
192+
193+
/* Downstream additions */
194+
struct rpi_firmware *fw;
195+
u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */
196+
u32 user_overclock_50; /* User's preferred overclock frequency */
197+
u32 overclock_50; /* Freq to use when 50MHz is requested (MHz) */
198+
u32 overclock; /* Current frequency if overclocked, else zero */
199+
bool reset_clock:1; /* Reset the clock for the next request */
190200
};
191201

192202
static void bcm2835_dumpcmd(struct bcm2835_host *host, struct mmc_command *cmd,
@@ -241,8 +251,11 @@ static void bcm2835_dumpregs(struct bcm2835_host *host)
241251

242252
static void bcm2835_reset_internal(struct bcm2835_host *host)
243253
{
254+
u32 cdiv = host->cdiv;
244255
u32 temp;
245256

257+
if (!cdiv)
258+
cdiv = readl(host->ioaddr + SDCDIV);
246259
writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD);
247260
writel(0, host->ioaddr + SDCMD);
248261
writel(0, host->ioaddr + SDARG);
@@ -263,9 +276,8 @@ static void bcm2835_reset_internal(struct bcm2835_host *host)
263276
msleep(20);
264277
writel(SDVDD_POWER_ON, host->ioaddr + SDVDD);
265278
msleep(20);
266-
host->clock = 0;
267279
writel(host->hcfg, host->ioaddr + SDHCFG);
268-
writel(host->cdiv, host->ioaddr + SDCDIV);
280+
writel(cdiv, host->ioaddr + SDCDIV);
269281
}
270282

271283
static void bcm2835_reset(struct mmc_host *mmc)
@@ -596,6 +608,25 @@ static void bcm2835_finish_request(struct bcm2835_host *host)
596608

597609
mrq = host->mrq;
598610

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

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

1118-
if (clock < 100000) {
1119-
/* Can't stop the clock, but make it as slow as possible
1120-
* to show willing
1121-
*/
1122-
host->cdiv = SDCDIV_MAX_CDIV;
1123-
writel(host->cdiv, host->ioaddr + SDCDIV);
1124-
return;
1125-
}
1154+
if (host->fw) {
1155+
u32 msg[3] = { clock, 0, 0 };
1156+
1157+
rpi_firmware_property(host->fw,
1158+
RPI_FIRMWARE_SET_SDHOST_CLOCK,
1159+
&msg, sizeof(msg));
1160+
1161+
clock = max(msg[1], msg[2]);
1162+
host->cdiv = 0;
1163+
} else {
1164+
if (clock < 100000) {
1165+
/* Can't stop the clock, but make it as slow as possible
1166+
* to show willing
1167+
*/
1168+
host->cdiv = SDCDIV_MAX_CDIV;
1169+
writel(host->cdiv, host->ioaddr + SDCDIV);
1170+
return;
1171+
}
11261172

1127-
div = host->max_clk / clock;
1128-
if (div < 2)
1129-
div = 2;
1130-
if ((host->max_clk / div) > clock)
1131-
div++;
1132-
div -= 2;
1173+
div = host->max_clk / clock;
1174+
if (div < 2)
1175+
div = 2;
1176+
if ((host->max_clk / div) > clock)
1177+
div++;
1178+
div -= 2;
11331179

1134-
if (div > SDCDIV_MAX_CDIV)
1135-
div = SDCDIV_MAX_CDIV;
1180+
if (div > SDCDIV_MAX_CDIV)
1181+
div = SDCDIV_MAX_CDIV;
11361182

1137-
clock = host->max_clk / (div + 2);
1138-
mmc->actual_clock = clock;
1183+
clock = host->max_clk / (div + 2);
1184+
1185+
host->cdiv = div;
1186+
writel(host->cdiv, host->ioaddr + SDCDIV);
1187+
}
11391188

11401189
/* Calibrate some delays */
11411190

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

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

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

11521228
static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -1176,6 +1252,9 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
11761252
return;
11771253
}
11781254

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

11811260
WARN_ON(host->mrq);
@@ -1199,7 +1278,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
11991278
return;
12001279
}
12011280

1202-
if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
1281+
if (host->use_dma && mrq->data && (mrq->data->blocks > host->pio_limit))
12031282
bcm2835_prepare_dma(host, mrq->data);
12041283

12051284
host->use_sbc = !!mrq->sbc && host->mrq->data &&
@@ -1334,8 +1413,8 @@ static int bcm2835_add_host(struct bcm2835_host *host)
13341413
}
13351414

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

@@ -1345,8 +1424,11 @@ static int bcm2835_add_host(struct bcm2835_host *host)
13451424
static int bcm2835_probe(struct platform_device *pdev)
13461425
{
13471426
struct device *dev = &pdev->dev;
1427+
struct device_node *node = dev->of_node;
13481428
struct bcm2835_host *host;
1429+
struct rpi_firmware *fw;
13491430
struct resource *iomem;
1431+
bool allow_dma = true;
13501432
struct mmc_host *mmc;
13511433
int ret;
13521434

@@ -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;
@@ -1382,6 +1481,24 @@ static int bcm2835_probe(struct platform_device *pdev)
13821481
/* Ignore errors to fall back to PIO mode */
13831482
}
13841483

1484+
fw = rpi_firmware_get(
1485+
of_parse_phandle(dev->of_node, "firmware", 0));
1486+
if (fw) {
1487+
u32 msg[3];
1488+
1489+
msg[0] = 0;
1490+
msg[1] = ~0;
1491+
msg[2] = ~0;
1492+
1493+
rpi_firmware_property(fw, RPI_FIRMWARE_SET_SDHOST_CLOCK,
1494+
&msg, sizeof(msg));
1495+
1496+
if (msg[1] != ~0)
1497+
host->fw = fw;
1498+
else
1499+
rpi_firmware_put(fw);
1500+
}
1501+
13851502
host->irq = platform_get_irq(pdev, 0);
13861503
if (host->irq < 0) {
13871504
ret = host->irq;

0 commit comments

Comments
 (0)