| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * OpenFirmware bindings for the MMC-over-SPI driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) MontaVista Software, Inc. 2008. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 9 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 10 | | - * Free Software Foundation; either version 2 of the License, or (at your |
|---|
| 11 | | - * option) any later version. |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | |
|---|
| 14 | 10 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 16 | 12 | #include <linux/device.h> |
|---|
| 17 | 13 | #include <linux/slab.h> |
|---|
| 18 | 14 | #include <linux/irq.h> |
|---|
| 19 | | -#include <linux/gpio.h> |
|---|
| 20 | 15 | #include <linux/of.h> |
|---|
| 21 | | -#include <linux/of_gpio.h> |
|---|
| 22 | 16 | #include <linux/of_irq.h> |
|---|
| 23 | 17 | #include <linux/spi/spi.h> |
|---|
| 24 | 18 | #include <linux/spi/mmc_spi.h> |
|---|
| .. | .. |
|---|
| 32 | 26 | |
|---|
| 33 | 27 | MODULE_LICENSE("GPL"); |
|---|
| 34 | 28 | |
|---|
| 35 | | -enum { |
|---|
| 36 | | - CD_GPIO = 0, |
|---|
| 37 | | - WP_GPIO, |
|---|
| 38 | | - NUM_GPIOS, |
|---|
| 39 | | -}; |
|---|
| 40 | | - |
|---|
| 41 | 29 | struct of_mmc_spi { |
|---|
| 42 | | - int gpios[NUM_GPIOS]; |
|---|
| 43 | | - bool alow_gpios[NUM_GPIOS]; |
|---|
| 44 | 30 | int detect_irq; |
|---|
| 45 | 31 | struct mmc_spi_platform_data pdata; |
|---|
| 46 | 32 | }; |
|---|
| .. | .. |
|---|
| 71 | 57 | struct device *dev = &spi->dev; |
|---|
| 72 | 58 | struct device_node *np = dev->of_node; |
|---|
| 73 | 59 | struct of_mmc_spi *oms; |
|---|
| 74 | | - const __be32 *voltage_ranges; |
|---|
| 75 | | - int num_ranges; |
|---|
| 76 | | - int i; |
|---|
| 77 | 60 | |
|---|
| 78 | 61 | if (dev->platform_data || !np) |
|---|
| 79 | 62 | return dev->platform_data; |
|---|
| .. | .. |
|---|
| 82 | 65 | if (!oms) |
|---|
| 83 | 66 | return NULL; |
|---|
| 84 | 67 | |
|---|
| 85 | | - voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); |
|---|
| 86 | | - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; |
|---|
| 87 | | - if (!voltage_ranges || !num_ranges) { |
|---|
| 88 | | - dev_err(dev, "OF: voltage-ranges unspecified\n"); |
|---|
| 68 | + if (mmc_of_parse_voltage(np, &oms->pdata.ocr_mask) <= 0) |
|---|
| 89 | 69 | goto err_ocr; |
|---|
| 90 | | - } |
|---|
| 91 | | - |
|---|
| 92 | | - for (i = 0; i < num_ranges; i++) { |
|---|
| 93 | | - const int j = i * 2; |
|---|
| 94 | | - u32 mask; |
|---|
| 95 | | - |
|---|
| 96 | | - mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), |
|---|
| 97 | | - be32_to_cpu(voltage_ranges[j + 1])); |
|---|
| 98 | | - if (!mask) { |
|---|
| 99 | | - dev_err(dev, "OF: voltage-range #%d is invalid\n", i); |
|---|
| 100 | | - goto err_ocr; |
|---|
| 101 | | - } |
|---|
| 102 | | - oms->pdata.ocr_mask |= mask; |
|---|
| 103 | | - } |
|---|
| 104 | | - |
|---|
| 105 | | - for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) { |
|---|
| 106 | | - enum of_gpio_flags gpio_flags; |
|---|
| 107 | | - |
|---|
| 108 | | - oms->gpios[i] = of_get_gpio_flags(np, i, &gpio_flags); |
|---|
| 109 | | - if (!gpio_is_valid(oms->gpios[i])) |
|---|
| 110 | | - continue; |
|---|
| 111 | | - |
|---|
| 112 | | - if (gpio_flags & OF_GPIO_ACTIVE_LOW) |
|---|
| 113 | | - oms->alow_gpios[i] = true; |
|---|
| 114 | | - } |
|---|
| 115 | | - |
|---|
| 116 | | - if (gpio_is_valid(oms->gpios[CD_GPIO])) { |
|---|
| 117 | | - oms->pdata.cd_gpio = oms->gpios[CD_GPIO]; |
|---|
| 118 | | - oms->pdata.flags |= MMC_SPI_USE_CD_GPIO; |
|---|
| 119 | | - if (!oms->alow_gpios[CD_GPIO]) |
|---|
| 120 | | - oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; |
|---|
| 121 | | - } |
|---|
| 122 | | - if (gpio_is_valid(oms->gpios[WP_GPIO])) { |
|---|
| 123 | | - oms->pdata.ro_gpio = oms->gpios[WP_GPIO]; |
|---|
| 124 | | - oms->pdata.flags |= MMC_SPI_USE_RO_GPIO; |
|---|
| 125 | | - if (!oms->alow_gpios[WP_GPIO]) |
|---|
| 126 | | - oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
|---|
| 127 | | - } |
|---|
| 128 | 70 | |
|---|
| 129 | 71 | oms->detect_irq = irq_of_parse_and_map(np, 0); |
|---|
| 130 | 72 | if (oms->detect_irq != 0) { |
|---|