summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-kernel-modules/brnkl/9-brnkl-rev10.mdef20
-rw-r--r--linux-kernel-modules/brnkl/brnkl.c452
-rw-r--r--linux-kernel-modules/brnkl/brnkl.h30
-rw-r--r--linux-kernel-modules/readme.md0
-rw-r--r--readme.md3
-rw-r--r--yocto-kernel-patches/disable-wm-audio.patch25
-rw-r--r--yocto-kernel-patches/enable-charging.patch12
-rw-r--r--yocto-kernel-patches/sd-card-gpio.patch14
8 files changed, 556 insertions, 0 deletions
diff --git a/linux-kernel-modules/brnkl/9-brnkl-rev10.mdef b/linux-kernel-modules/brnkl/9-brnkl-rev10.mdef
new file mode 100644
index 0000000..3ce593b
--- /dev/null
+++ b/linux-kernel-modules/brnkl/9-brnkl-rev10.mdef
@@ -0,0 +1,20 @@
+cflags:
+{
+ // Needed for lsm6ds3 platform data type definition
+ -I${MANGOH_ROOT}/linux_kernel_modules/lsm6ds3
+ -I${MANGOH_ROOT}/linux_kernel_modules/ltc294x
+ -I${MANGOH_ROOT}/linux_kernel_modules/bq24296
+ -I${MANGOH_ROOT}/linux_kernel_modules/iot_slot
+ -I${MANGOH_ROOT}/linux_kernel_modules/led
+ -I${MANGOH_ROOT}/linux_kernel_modules/bmp280
+}
+
+sources:
+{
+ brnkl.c
+}
+
+params:
+{
+ revision = "dv5"
+}
diff --git a/linux-kernel-modules/brnkl/brnkl.c b/linux-kernel-modules/brnkl/brnkl.c
new file mode 100644
index 0000000..913c30c
--- /dev/null
+++ b/linux-kernel-modules/brnkl/brnkl.c
@@ -0,0 +1,452 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca954x.h>
+#include <linux/i2c/sx150x.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/gpio/driver.h>
+
+#include "lsm6ds3_platform_data.h"
+#include "ltc294x-platform-data.h"
+#include "bq24190-platform-data.h"
+
+#include "brnkl.h"
+#include "iot-slot.h"
+#include "led.h"
+
+/*
+ *-----------------------------------------------------------------------------
+ * Constants
+ *-----------------------------------------------------------------------------
+ */
+#define MANGOH_RED_I2C_SW_BUS_BASE (PRIMARY_I2C_BUS + 0)
+#define MANGOH_RED_I2C_BUS_IOT0 (MANGOH_RED_I2C_SW_BUS_BASE + 0)
+#define MANGOH_RED_I2C_BUS_BATTERY_CHARGER (MANGOH_RED_I2C_SW_BUS_BASE + 0)
+#define MANGOH_RED_I2C_BUS_USB_HUB (MANGOH_RED_I2C_SW_BUS_BASE + 1)
+#define MANGOH_RED_I2C_BUS_GPIO_EXPANDER (MANGOH_RED_I2C_SW_BUS_BASE + 2)
+#define MANGOH_RED_I2C_BUS_EXP (MANGOH_RED_I2C_SW_BUS_BASE + 3)
+
+/*
+ *-----------------------------------------------------------------------------
+ * Types
+ *-----------------------------------------------------------------------------
+ */
+enum mangoh_red_board_rev {
+ MANGOH_RED_BOARD_REV_DV2,
+ MANGOH_RED_BOARD_REV_DV3,
+ MANGOH_RED_BOARD_REV_DV5,
+};
+
+/*
+ *-----------------------------------------------------------------------------
+ * Static Function Declarations
+ *-----------------------------------------------------------------------------
+ */
+static void mangoh_red_release(struct device* dev);
+static int mangoh_red_probe(struct platform_device* pdev);
+static int mangoh_red_remove(struct platform_device* pdev);
+static void mangoh_red_led_release(struct device* dev);
+#ifdef ENABLE_IOT_SLOT
+static void mangoh_red_iot_slot_release(struct device* dev);
+static int mangoh_red_iot_slot_request_i2c(struct i2c_adapter** adapter);
+static int mangoh_red_iot_slot_release_i2c(struct i2c_adapter** adapter);
+static int mangoh_red_iot_slot_request_spi(struct spi_master** spi_master,
+ int* cs);
+static int mangoh_red_iot_slot_release_spi(void);
+static int mangoh_red_iot_slot_request_sdio(void);
+static int mangoh_red_iot_slot_release_sdio(void);
+static int mangoh_red_iot_slot_request_pcm(void);
+static int mangoh_red_iot_slot_release_pcm(void);
+#endif /* ENABLE_IOT_SLOT */
+
+/*
+ *-----------------------------------------------------------------------------
+ * Variables
+ *-----------------------------------------------------------------------------
+ */
+
+static char* revision_dv2 = "dv2";
+static char* revision_dv3 = "dv3";
+static char* revision_dv5 = "dv5";
+
+static char* revision = "dv5";
+module_param(revision, charp, S_IRUGO);
+MODULE_PARM_DESC(revision, "mangOH Red board revision");
+
+static struct platform_driver mangoh_red_driver = {
+ .probe = mangoh_red_probe,
+ .remove = mangoh_red_remove,
+ .driver =
+ {
+ .name = "mangoh red",
+ .owner = THIS_MODULE,
+ .bus = &platform_bus_type,
+ },
+};
+
+static struct mangoh_red_platform_data {
+ enum mangoh_red_board_rev board_rev;
+} mangoh_red_pdata;
+
+static struct mangoh_red_driver_data {
+ struct i2c_client* accelerometer;
+ struct i2c_client* pressure;
+ struct i2c_client* battery_gauge;
+ struct i2c_client* battery_charger;
+ bool mux_initialized;
+ bool iot_slot_registered;
+ bool led_registered;
+} mangoh_red_driver_data = {
+ .mux_initialized = false,
+ .iot_slot_registered = false,
+ .led_registered = false,
+};
+
+static struct platform_device mangoh_red_device = {
+ .name = "mangoh red",
+ .id = -1,
+ .dev =
+ {
+ .release = mangoh_red_release,
+ .platform_data = &mangoh_red_pdata,
+ },
+};
+
+static struct pca954x_platform_mode mangoh_red_pca954x_adap_modes[] = {
+ {.adap_id = MANGOH_RED_I2C_SW_BUS_BASE + 0,
+ .deselect_on_exit = 1,
+ .class = 0},
+ {.adap_id = MANGOH_RED_I2C_SW_BUS_BASE + 1,
+ .deselect_on_exit = 1,
+ .class = 0},
+ {.adap_id = MANGOH_RED_I2C_SW_BUS_BASE + 2,
+ .deselect_on_exit = 1,
+ .class = 0},
+ {.adap_id = MANGOH_RED_I2C_SW_BUS_BASE + 3,
+ .deselect_on_exit = 1,
+ .class = 0},
+};
+static struct pca954x_platform_data mangoh_red_pca954x_pdata = {
+ mangoh_red_pca954x_adap_modes, ARRAY_SIZE(mangoh_red_pca954x_adap_modes),
+};
+static const struct i2c_board_info mangoh_red_pca954x_device_info = {
+ I2C_BOARD_INFO("pca9546", 0x71), .platform_data = &mangoh_red_pca954x_pdata,
+};
+
+static struct sx150x_platform_data mangoh_red_gpio_expander_platform_data = {
+ .gpio_base = -1,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0,
+ .io_pulldn_ena = 0,
+ .io_open_drain_ena = 0,
+ .io_polarity = 0,
+ .irq_summary = -1,
+ .irq_base = -1,
+ .reset_during_probe = true,
+
+};
+static const struct i2c_board_info mangoh_red_gpio_expander_devinfo = {
+ I2C_BOARD_INFO("sx1509q", 0x3e),
+ .platform_data = &mangoh_red_gpio_expander_platform_data, .irq = 0,
+};
+
+static struct i2c_board_info mangoh_red_bmi160_devinfo = {
+ I2C_BOARD_INFO("bmi160", 0x68),
+};
+
+static struct lsm6ds3_platform_data mangoh_red_lsm6ds3_platform_data = {
+ .drdy_int_pin = 1,
+};
+static struct i2c_board_info mangoh_red_lsm6ds3_devinfo = {
+ I2C_BOARD_INFO("lsm6ds3", 0x6A),
+ .platform_data = &mangoh_red_lsm6ds3_platform_data,
+};
+
+static struct i2c_board_info mangoh_red_pressure_devinfo = {
+ I2C_BOARD_INFO("bme280", 0x76),
+};
+
+static struct ltc294x_platform_data mangoh_red_battery_gauge_platform_data = {
+ .r_sense = 18,
+ .prescaler_exp = 32,
+ .name = "LTC2942",
+};
+static struct i2c_board_info mangoh_red_battery_gauge_devinfo = {
+ I2C_BOARD_INFO("ltc2942", 0x64),
+ .platform_data = &mangoh_red_battery_gauge_platform_data,
+};
+
+static struct i2c_board_info mangoh_red_battery_charger_devinfo = {
+ I2C_BOARD_INFO("bq24190", 0x6B),
+};
+
+#ifdef ENABLE_IOT_SLOT
+static struct iot_slot_platform_data mangoh_red_iot_slot_pdata = {
+ .gpio = {CF3_GPIO42, CF3_GPIO13, CF3_GPIO7, CF3_GPIO8},
+ .reset_gpio = CF3_GPIO2,
+ .card_detect_gpio = CF3_GPIO33,
+ .request_i2c = mangoh_red_iot_slot_request_i2c,
+ .release_i2c = mangoh_red_iot_slot_release_i2c,
+ .request_spi = mangoh_red_iot_slot_request_spi,
+ .release_spi = mangoh_red_iot_slot_release_spi,
+ .request_sdio = mangoh_red_iot_slot_request_sdio,
+ .release_sdio = mangoh_red_iot_slot_release_sdio,
+ .request_pcm = mangoh_red_iot_slot_request_pcm,
+ .release_pcm = mangoh_red_iot_slot_release_pcm,
+};
+
+static struct platform_device mangoh_red_iot_slot = {
+ .name = "iot-slot",
+ .id = 0, /* Means IoT slot 0 */
+ .dev =
+ {
+ .platform_data = &mangoh_red_iot_slot_pdata,
+ .release = mangoh_red_iot_slot_release,
+ },
+};
+#endif /* ENABLE_IOT_SLOT */
+
+static struct led_platform_data mangoh_red_led_pdata = {
+ .gpio = -1,
+};
+
+static struct platform_device mangoh_red_led = {
+ .name = "led",
+ .dev =
+ {
+ .platform_data = &mangoh_red_led_pdata,
+ .release = mangoh_red_led_release,
+ },
+};
+
+static void mangoh_red_release(struct device* dev) {
+ /* Nothing alloc'd, so nothign to free */
+}
+
+static int mangoh_red_probe(struct platform_device* pdev) {
+ int ret = 0;
+#ifdef ENABLE_IOT_SLOT
+ int sdio_mux_gpio;
+ int pcm_mux_gpio;
+#endif /* ENABLE_IOT_SLOT */
+ struct gpio_chip* gpio_expander;
+ struct i2c_board_info* accelerometer_board_info;
+ struct i2c_adapter* other_adapter = NULL;
+ struct i2c_adapter* main_adapter;
+
+ dev_info(&pdev->dev, "%s(): probe\n", __func__);
+
+ main_adapter = i2c_get_adapter(PRIMARY_I2C_BUS);
+ if (!main_adapter) {
+ dev_err(&pdev->dev, "Failed to get primary I2C adapter (%d).\n",
+ PRIMARY_I2C_BUS);
+ ret = -ENODEV;
+ goto done;
+ }
+
+ /*
+ * This is a workaround of questionable validity for USB issues first
+ * seen on the mangOH Green.
+ */
+ msleep(5000);
+
+ platform_set_drvdata(pdev, &mangoh_red_driver_data);
+
+ /* Map the accelerometer */
+ dev_dbg(&pdev->dev, "mapping accelerometer\n");
+ /*
+ * Pins 11 and 12 of the gpio expander are connected to bmi160's INT1
+ * and INT2 pins respectively. It does not appear that the bmi160 driver
+ * makes use of these interrupt pins.
+ */
+ accelerometer_board_info =
+ mangoh_red_pdata.board_rev == MANGOH_RED_BOARD_REV_DV2
+ ? &mangoh_red_lsm6ds3_devinfo
+ : &mangoh_red_bmi160_devinfo;
+ mangoh_red_driver_data.accelerometer =
+ i2c_new_device(main_adapter, accelerometer_board_info);
+ if (!mangoh_red_driver_data.accelerometer) {
+ dev_err(&pdev->dev, "Accelerometer is missing\n");
+ return -ENODEV;
+ }
+
+ /* Map the I2C BMP280 pressure sensor */
+ dev_dbg(&pdev->dev, "mapping bmp280 pressure sensor\n");
+ mangoh_red_driver_data.pressure =
+ i2c_new_device(main_adapter, &mangoh_red_pressure_devinfo);
+ if (!mangoh_red_driver_data.pressure) {
+ dev_err(&pdev->dev, "Pressure sensor is missing\n");
+ return -ENODEV;
+ }
+
+ /* Map the I2C BQ24296 driver: for now use the BQ24190 driver code */
+ dev_dbg(&pdev->dev, "mapping bq24296 driver\n");
+ other_adapter = i2c_get_adapter(MANGOH_RED_I2C_BUS_BATTERY_CHARGER);
+ if (!other_adapter) {
+ dev_err(&pdev->dev, "No I2C bus %d.\n", MANGOH_RED_I2C_BUS_BATTERY_CHARGER);
+ ret = -ENODEV;
+ goto cleanup;
+ }
+ mangoh_red_driver_data.battery_charger =
+ i2c_new_device(other_adapter, &mangoh_red_battery_charger_devinfo);
+ i2c_put_adapter(other_adapter);
+ if (!mangoh_red_driver_data.battery_charger) {
+ dev_err(&pdev->dev, "battery charger is missing\n");
+ ret = -ENODEV;
+ goto cleanup;
+ }
+
+ if (mangoh_red_pdata.board_rev != MANGOH_RED_BOARD_REV_DV3) {
+ /* Map the I2C ltc2942 battery gauge */
+ dev_dbg(&pdev->dev, "mapping ltc2942 battery gauge\n");
+ other_adapter =
+ i2c_get_adapter(MANGOH_RED_I2C_BUS_BATTERY_CHARGER);
+ if (!other_adapter) {
+ dev_err(&pdev->dev, "No I2C bus %d.\n",
+ MANGOH_RED_I2C_BUS_BATTERY_CHARGER);
+ ret = -ENODEV;
+ goto cleanup;
+ }
+ mangoh_red_driver_data.battery_gauge = i2c_new_device(
+ other_adapter, &mangoh_red_battery_gauge_devinfo);
+ i2c_put_adapter(other_adapter);
+ if (!mangoh_red_driver_data.battery_gauge) {
+ dev_err(&pdev->dev, "battery gauge is missing\n");
+ ret = -ENODEV;
+ goto cleanup;
+ }
+ }
+/*
+ * TODO:
+ * 3503 USB Hub: 0x08
+ * Looks like there is a driver in the wp85 kernel source at
+ * drivers/usb/misc/usb3503.c. I'm not really sure what benefit is
+ * achieved through using this driver.
+ */
+
+cleanup:
+ i2c_put_adapter(main_adapter);
+ if (ret != 0)
+ mangoh_red_remove(pdev);
+done:
+ return ret;
+}
+
+static void try_unregister_i2c_device(struct i2c_client* client) {
+ if (client != NULL) {
+ i2c_unregister_device(client);
+ i2c_put_adapter(client->adapter);
+ }
+}
+
+static int mangoh_red_remove(struct platform_device* pdev) {
+ struct mangoh_red_driver_data* dd = platform_get_drvdata(pdev);
+
+ dev_info(&pdev->dev, "Removing mangoh red platform device\n");
+
+#if 0
+ if (mangoh_red_pdata.board_rev != MANGOH_RED_BOARD_REV_DV3)
+ try_unregister_i2c_device(dd->battery_gauge);
+#endif
+
+ try_unregister_i2c_device(dd->battery_charger);
+ try_unregister_i2c_device(dd->pressure);
+ try_unregister_i2c_device(dd->accelerometer);
+
+ if (dd->led_registered)
+ platform_device_unregister(&mangoh_red_led);
+
+ return 0;
+}
+
+/* Release function is needed to avoid warning when device is deleted */
+#ifdef ENABLE_IOT_SLOT
+static void mangoh_red_iot_slot_release(struct device* dev) { /* do nothing */
+}
+#endif /* ENABLE_IOT_SLOT */
+static void mangoh_red_led_release(struct device* dev) { /* do nothing */
+}
+
+#ifdef ENABLE_IOT_SLOT
+static int mangoh_red_iot_slot_request_i2c(struct i2c_adapter** adapter) {
+ *adapter = i2c_get_adapter(MANGOH_RED_I2C_BUS_IOT0);
+ return *adapter != NULL ? 0 : -EINVAL;
+}
+
+static int mangoh_red_iot_slot_release_i2c(struct i2c_adapter** adapter) {
+ i2c_put_adapter(*adapter);
+ *adapter = NULL;
+ return 0;
+}
+
+static int mangoh_red_iot_slot_request_spi(struct spi_master** spi_master,
+ int* cs) {
+ *spi_master = spi_busnum_to_master(PRIMARY_SPI_BUS);
+ *cs = 0;
+ if (!*spi_master) {
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int mangoh_red_iot_slot_release_spi(void) {
+ return 0; /* Nothing to do */
+}
+
+static int mangoh_red_iot_slot_request_sdio(void) {
+ return mangoh_red_mux_sdio_select(SDIO_SELECTION_IOT_SLOT);
+}
+
+static int mangoh_red_iot_slot_release_sdio(void) {
+ return mangoh_red_mux_sdio_release(SDIO_SELECTION_IOT_SLOT);
+}
+
+static int mangoh_red_iot_slot_request_pcm(void) {
+ return mangoh_red_mux_pcm_select(PCM_SELECTION_IOT_SLOT);
+}
+
+static int mangoh_red_iot_slot_release_pcm(void) {
+ return mangoh_red_mux_pcm_release(PCM_SELECTION_IOT_SLOT);
+}
+#endif /* ENABLE_IOT_SLOT */
+
+static int __init mangoh_red_init(void) {
+ platform_driver_register(&mangoh_red_driver);
+ printk(KERN_DEBUG "mangoh: registered platform driver\n");
+
+ if (strcmp(revision, revision_dv2) == 0) {
+ mangoh_red_pdata.board_rev = MANGOH_RED_BOARD_REV_DV2;
+ } else if (strcmp(revision, revision_dv3) == 0) {
+ mangoh_red_pdata.board_rev = MANGOH_RED_BOARD_REV_DV3;
+ } else if (strcmp(revision, revision_dv5) == 0) {
+ mangoh_red_pdata.board_rev = MANGOH_RED_BOARD_REV_DV5;
+ } else {
+ pr_err("%s: Unsupported mangOH Red board revision (%s)\n", __func__,
+ revision);
+ return -ENODEV; /* TODO: better value? */
+ }
+
+ if (platform_device_register(&mangoh_red_device)) {
+ platform_driver_unregister(&mangoh_red_driver);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit mangoh_red_exit(void) {
+ platform_device_unregister(&mangoh_red_device);
+ platform_driver_unregister(&mangoh_red_driver);
+}
+
+module_init(mangoh_red_init);
+module_exit(mangoh_red_exit);
+
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "mangoh red");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sierra Wireless");
+MODULE_DESCRIPTION("Add devices on mangOH Red hardware board");
+MODULE_VERSION("1.0");
diff --git a/linux-kernel-modules/brnkl/brnkl.h b/linux-kernel-modules/brnkl/brnkl.h
new file mode 100644
index 0000000..780597e
--- /dev/null
+++ b/linux-kernel-modules/brnkl/brnkl.h
@@ -0,0 +1,30 @@
+#ifndef BRNKL_H
+#define BRNKL_H
+
+#include <linux/kernel.h>
+
+/* TODO: There should be a better way to convert from WP GPIO numbers to real
+ * GPIO numbers */
+#if defined(CONFIG_ARCH_MSM9615) /* For WPX5XX */
+#define PRIMARY_I2C_BUS (0)
+#define PRIMARY_SPI_BUS (0)
+
+#define CF3_GPIO42 (80)
+#define CF3_GPIO13 (34)
+#define CF3_GPIO7 (79)
+#define CF3_GPIO8 (29)
+#define CF3_GPIO2 (59)
+#define CF3_GPIO33 (78)
+#elif defined(CONFIG_ARCH_MDM9607) /* For WP76XX */
+#define PRIMARY_I2C_BUS (4)
+#define PRIMARY_SPI_BUS (1)
+
+#define CF3_GPIO42 (79)
+#define CF3_GPIO13 (76)
+#define CF3_GPIO7 (16)
+#define CF3_GPIO8 (58)
+#define CF3_GPIO2 (38)
+#define CF3_GPIO33 (78)
+#endif
+
+#endif
diff --git a/linux-kernel-modules/readme.md b/linux-kernel-modules/readme.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/linux-kernel-modules/readme.md
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..4900d5b
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,3 @@
+# mangoh-red-kernel-changes
+
+A collection of small changes to WP85/MangOH Red related kernel modules. Sharing this to help debug the issue being discussed here: https://forum.mangoh.io/t/gpio-stops-working-after-several-hours/
diff --git a/yocto-kernel-patches/disable-wm-audio.patch b/yocto-kernel-patches/disable-wm-audio.patch
new file mode 100644
index 0000000..9d61096
--- /dev/null
+++ b/yocto-kernel-patches/disable-wm-audio.patch
@@ -0,0 +1,25 @@
+diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
+index 80c4272c60e..61031eb2e37 100644
+--- a/arch/arm/mach-msm/board-9615.c
++++ b/arch/arm/mach-msm/board-9615.c
+@@ -1519,20 +1519,6 @@ static void __init msm9615_i2c_init(void)
+ &msm9615_i2c_qup_gsbi5_pdata;
+ #endif /* CONFIG_SIERRA */
+
+-#ifdef CONFIG_MFD_WM8944
+- if(bssupport(BSFEATURE_WM8944) == true)
+- {
+- for (i = 0; i < ARRAY_SIZE(msm9615_i2c_devices_wm8944); ++i) {
+- if (msm9615_i2c_devices_wm8944[i].machs & mach_mask) {
+- i2c_register_board_info(
+- msm9615_i2c_devices_wm8944[i].bus,
+- msm9615_i2c_devices_wm8944[i].info,
+- msm9615_i2c_devices_wm8944[i].len);
+- }
+- }
+- }
+- else
+-#endif
+ {
+ for (i = 0; i < ARRAY_SIZE(msm9615_i2c_devices); ++i) {
+ if (msm9615_i2c_devices[i].machs & mach_mask) {
diff --git a/yocto-kernel-patches/enable-charging.patch b/yocto-kernel-patches/enable-charging.patch
new file mode 100644
index 0000000..48452eb
--- /dev/null
+++ b/yocto-kernel-patches/enable-charging.patch
@@ -0,0 +1,12 @@
+diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
+index 44420d1..35e0093 100644
+--- a/drivers/power/power_supply_sysfs.c
++++ b/drivers/power/power_supply_sysfs.c
+@@ -139,6 +139,7 @@ static struct device_attribute power_supply_attrs[] = {
+ POWER_SUPPLY_ATTR(health),
+ POWER_SUPPLY_ATTR(present),
+ POWER_SUPPLY_ATTR(online),
++ POWER_SUPPLY_ATTR(charging_enabled),
+ POWER_SUPPLY_ATTR(authentic),
+ POWER_SUPPLY_ATTR(technology),
+ POWER_SUPPLY_ATTR(cycle_count),
diff --git a/yocto-kernel-patches/sd-card-gpio.patch b/yocto-kernel-patches/sd-card-gpio.patch
new file mode 100644
index 0000000..27b1051
--- /dev/null
+++ b/yocto-kernel-patches/sd-card-gpio.patch
@@ -0,0 +1,14 @@
+diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
+index 1c6f951..64d4329 100644
+--- a/arch/arm/mach-msm/board-9615-storage.c
++++ b/arch/arm/mach-msm/board-9615-storage.c
+@@ -27,7 +27,8 @@
+ #if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT) \
+ || defined(CONFIG_MMC_MSM_SDC2_SUPPORT))
+
+-#define GPIO_SDC1_HW_DET 80
++// #define GPIO_SDC1_HW_DET 80
++#define GPIO_SDC1_HW_DET 49
+ #define GPIO_SDC2_DAT1_WAKEUP 26
+
+ /* MDM9x15 has 2 SDCC controllers */