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 
17 struct bt_sfi_data {
18 	struct device *dev;
19 	const char *name;
20 	int (*setup)(struct bt_sfi_data *ddata);
21 };
22 
23 static 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 
tng_bt_sfi_setup(struct bt_sfi_data * ddata)37 static 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 
59 static struct bt_sfi_data tng_bt_sfi_data __initdata = {
60 	.setup	= tng_bt_sfi_setup,
61 };
62 
63 static 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 
bt_sfi_init(void)68 static 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 }
101 device_initcall(bt_sfi_init);
102