aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@bootlin.com>2018-03-08 09:52:51 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2018-03-15 09:43:22 -0400
commit774c010350a16f44705971e8aff457580628c76e (patch)
tree865a0ad052c7eee1dbf9622ccf00efeb1aa2864f
parente382ab741252471383e9990583258e3054f66963 (diff)
mmc: sunxi: Move resources management to separate functions
We've had all our resources management, and especially the clocks and reset sequence, done directly as part of the probe. As we want to implement runtime_pm, we'll obviously want to have that moved outside of the probe so that we can call do it in our runtime suspend and resume hooks without too much duplication. Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sunxi-mmc.c142
1 files changed, 82 insertions, 60 deletions
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index bad612d6f879..3601746d37a9 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -268,6 +268,7 @@ struct sunxi_mmc_cfg {
268}; 268};
269 269
270struct sunxi_mmc_host { 270struct sunxi_mmc_host {
271 struct device *dev;
271 struct mmc_host *mmc; 272 struct mmc_host *mmc;
272 struct reset_control *reset; 273 struct reset_control *reset;
273 const struct sunxi_mmc_cfg *cfg; 274 const struct sunxi_mmc_cfg *cfg;
@@ -1165,6 +1166,80 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
1165}; 1166};
1166MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); 1167MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
1167 1168
1169static int sunxi_mmc_enable(struct sunxi_mmc_host *host)
1170{
1171 int ret;
1172
1173 ret = clk_prepare_enable(host->clk_ahb);
1174 if (ret) {
1175 dev_err(dev, "Couldn't enable the bus clocks (%d)\n", ret);
1176 return ret;
1177 }
1178
1179 ret = clk_prepare_enable(host->clk_mmc);
1180 if (ret) {
1181 dev_err(host->dev, "Enable mmc clk err %d\n", ret);
1182 goto error_disable_clk_ahb;
1183 }
1184
1185 ret = clk_prepare_enable(host->clk_output);
1186 if (ret) {
1187 dev_err(host->dev, "Enable output clk err %d\n", ret);
1188 goto error_disable_clk_mmc;
1189 }
1190
1191 ret = clk_prepare_enable(host->clk_sample);
1192 if (ret) {
1193 dev_err(host->dev, "Enable sample clk err %d\n", ret);
1194 goto error_disable_clk_output;
1195 }
1196
1197 if (!IS_ERR(host->reset)) {
1198 ret = reset_control_reset(host->reset);
1199 if (ret) {
1200 dev_err(dev, "Couldn't reset the MMC controller (%d)\n",
1201 ret);
1202 goto error_disable_clk_sample;
1203 }
1204 }
1205
1206 /*
1207 * Sometimes the controller asserts the irq on boot for some reason,
1208 * make sure the controller is in a sane state before enabling irqs.
1209 */
1210 ret = sunxi_mmc_reset_host(host);
1211 if (ret)
1212 goto error_assert_reset;
1213
1214 return 0;
1215
1216error_assert_reset:
1217 if (!IS_ERR(host->reset))
1218 reset_control_assert(host->reset);
1219error_disable_clk_sample:
1220 clk_disable_unprepare(host->clk_sample);
1221error_disable_clk_output:
1222 clk_disable_unprepare(host->clk_output);
1223error_disable_clk_mmc:
1224 clk_disable_unprepare(host->clk_mmc);
1225error_disable_clk_ahb:
1226 clk_disable_unprepare(host->clk_ahb);
1227 return ret;
1228}
1229
1230static void sunxi_mmc_disable(struct sunxi_mmc_host *host)
1231{
1232 sunxi_mmc_reset_host(host);
1233
1234 if (!IS_ERR(host->reset))
1235 reset_control_assert(host->reset);
1236
1237 clk_disable_unprepare(host->clk_sample);
1238 clk_disable_unprepare(host->clk_output);
1239 clk_disable_unprepare(host->clk_mmc);
1240 clk_disable_unprepare(host->clk_ahb);
1241}
1242
1168static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, 1243static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
1169 struct platform_device *pdev) 1244 struct platform_device *pdev)
1170{ 1245{
@@ -1214,66 +1289,21 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
1214 if (PTR_ERR(host->reset) == -EPROBE_DEFER) 1289 if (PTR_ERR(host->reset) == -EPROBE_DEFER)
1215 return PTR_ERR(host->reset); 1290 return PTR_ERR(host->reset);
1216 1291
1217 ret = clk_prepare_enable(host->clk_ahb); 1292 ret = sunxi_mmc_enable(host);
1218 if (ret) {
1219 dev_err(&pdev->dev, "Enable ahb clk err %d\n", ret);
1220 return ret;
1221 }
1222
1223 ret = clk_prepare_enable(host->clk_mmc);
1224 if (ret) {
1225 dev_err(&pdev->dev, "Enable mmc clk err %d\n", ret);
1226 goto error_disable_clk_ahb;
1227 }
1228
1229 ret = clk_prepare_enable(host->clk_output);
1230 if (ret) {
1231 dev_err(&pdev->dev, "Enable output clk err %d\n", ret);
1232 goto error_disable_clk_mmc;
1233 }
1234
1235 ret = clk_prepare_enable(host->clk_sample);
1236 if (ret) {
1237 dev_err(&pdev->dev, "Enable sample clk err %d\n", ret);
1238 goto error_disable_clk_output;
1239 }
1240
1241 if (!IS_ERR(host->reset)) {
1242 ret = reset_control_reset(host->reset);
1243 if (ret) {
1244 dev_err(&pdev->dev, "reset err %d\n", ret);
1245 goto error_disable_clk_sample;
1246 }
1247 }
1248
1249 /*
1250 * Sometimes the controller asserts the irq on boot for some reason,
1251 * make sure the controller is in a sane state before enabling irqs.
1252 */
1253 ret = sunxi_mmc_reset_host(host);
1254 if (ret) 1293 if (ret)
1255 goto error_assert_reset; 1294 return ret;
1256 1295
1257 host->irq = platform_get_irq(pdev, 0); 1296 host->irq = platform_get_irq(pdev, 0);
1258 if (host->irq <= 0) { 1297 if (host->irq <= 0) {
1259 ret = -EINVAL; 1298 ret = -EINVAL;
1260 goto error_assert_reset; 1299 goto error_disable_mmc;
1261 } 1300 }
1262 1301
1263 return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 1302 return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq,
1264 sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); 1303 sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host);
1265 1304
1266error_assert_reset: 1305error_disable_mmc:
1267 if (!IS_ERR(host->reset)) 1306 sunxi_mmc_disable(host);
1268 reset_control_assert(host->reset);
1269error_disable_clk_sample:
1270 clk_disable_unprepare(host->clk_sample);
1271error_disable_clk_output:
1272 clk_disable_unprepare(host->clk_output);
1273error_disable_clk_mmc:
1274 clk_disable_unprepare(host->clk_mmc);
1275error_disable_clk_ahb:
1276 clk_disable_unprepare(host->clk_ahb);
1277 return ret; 1307 return ret;
1278} 1308}
1279 1309
@@ -1290,6 +1320,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
1290 } 1320 }
1291 1321
1292 host = mmc_priv(mmc); 1322 host = mmc_priv(mmc);
1323 host->dev = &pdev->dev;
1293 host->mmc = mmc; 1324 host->mmc = mmc;
1294 spin_lock_init(&host->lock); 1325 spin_lock_init(&host->lock);
1295 1326
@@ -1370,16 +1401,7 @@ static int sunxi_mmc_remove(struct platform_device *pdev)
1370 1401
1371 mmc_remove_host(mmc); 1402 mmc_remove_host(mmc);
1372 disable_irq(host->irq); 1403 disable_irq(host->irq);
1373 sunxi_mmc_reset_host(host); 1404 sunxi_mmc_disable(host);
1374
1375 if (!IS_ERR(host->reset))
1376 reset_control_assert(host->reset);
1377
1378 clk_disable_unprepare(host->clk_sample);
1379 clk_disable_unprepare(host->clk_output);
1380 clk_disable_unprepare(host->clk_mmc);
1381 clk_disable_unprepare(host->clk_ahb);
1382
1383 dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); 1405 dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
1384 mmc_free_host(mmc); 1406 mmc_free_host(mmc);
1385 1407