linux/arch/x86/platform/intel-mid/device_libs/platform_bt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Bluetooth platform data initialization file
   4 *
   5 * (C) Copyright 2017 Intel Corporation
   6 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
   7 */
   8
   9#include <linux/gpio/machine.h>
  10#include <linux/pci.h>
  11#include <linux/platform_device.h>
  12
  13#include <asm/cpu_device_id.h>
  14#include <asm/intel-family.h>
  15#include <asm/intel-mid.h>
  16
  17struct bt_sfi_data {
  18        struct device *dev;
  19        const char *name;
  20        int (*setup)(struct bt_sfi_data *ddata);
  21};
  22
  23static struct gpiod_lookup_table tng_bt_sfi_gpio_table = {
  24        .dev_id = "hci_bcm",
  25        .table  = {
  26                GPIO_LOOKUP("0000:00:0c.0", -1, "device-wakeup", GPIO_ACTIVE_HIGH),
  27                GPIO_LOOKUP("0000:00:0c.0", -1, "shutdown",      GPIO_ACTIVE_HIGH),
  28                GPIO_LOOKUP("0000:00:0c.0", -1, "host-wakeup",   GPIO_ACTIVE_HIGH),
  29                { },
  30        },
  31};
  32
  33#define TNG_BT_SFI_GPIO_DEVICE_WAKEUP   "bt_wakeup"
  34#define TNG_BT_SFI_GPIO_SHUTDOWN        "BT-reset"
  35#define TNG_BT_SFI_GPIO_HOST_WAKEUP     "bt_uart_enable"
  36
  37static int __init tng_bt_sfi_setup(struct bt_sfi_data *ddata)
  38{
  39        struct gpiod_lookup_table *table = &tng_bt_sfi_gpio_table;
  40        struct gpiod_lookup *lookup = table->table;
  41        struct pci_dev *pdev;
  42
  43        /* Connected to /dev/ttyS0 */
  44        pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(4, 1));
  45        if (!pdev)
  46                return -ENODEV;
  47
  48        ddata->dev = &pdev->dev;
  49        ddata->name = table->dev_id;
  50
  51        lookup[0].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_DEVICE_WAKEUP);
  52        lookup[1].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_SHUTDOWN);
  53        lookup[2].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_HOST_WAKEUP);
  54
  55        gpiod_add_lookup_table(table);
  56        return 0;
  57}
  58
  59static struct bt_sfi_data tng_bt_sfi_data __initdata = {
  60        .setup  = tng_bt_sfi_setup,
  61};
  62
  63static const struct x86_cpu_id bt_sfi_cpu_ids[] = {
  64        X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &tng_bt_sfi_data),
  65        {}
  66};
  67
  68static int __init bt_sfi_init(void)
  69{
  70        struct platform_device_info info;
  71        struct platform_device *pdev;
  72        const struct x86_cpu_id *id;
  73        struct bt_sfi_data *ddata;
  74        int ret;
  75
  76        id = x86_match_cpu(bt_sfi_cpu_ids);
  77        if (!id)
  78                return -ENODEV;
  79
  80        ddata = (struct bt_sfi_data *)id->driver_data;
  81        if (!ddata)
  82                return -ENODEV;
  83
  84        ret = ddata->setup(ddata);
  85        if (ret)
  86                return ret;
  87
  88        memset(&info, 0, sizeof(info));
  89        info.fwnode     = ddata->dev->fwnode;
  90        info.parent     = ddata->dev;
  91        info.name       = ddata->name,
  92        info.id         = PLATFORM_DEVID_NONE,
  93
  94        pdev = platform_device_register_full(&info);
  95        if (IS_ERR(pdev))
  96                return PTR_ERR(pdev);
  97
  98        dev_info(ddata->dev, "Registered Bluetooth device: %s\n", ddata->name);
  99        return 0;
 100}
 101device_initcall(bt_sfi_init);
 102