xref: /openbmc/linux/drivers/net/fjes/fjes_main.c (revision 658d439b22924796d00f03282135a356f47cc64e)
1*658d439bSTaku Izumi /*
2*658d439bSTaku Izumi  *  FUJITSU Extended Socket Network Device driver
3*658d439bSTaku Izumi  *  Copyright (c) 2015 FUJITSU LIMITED
4*658d439bSTaku Izumi  *
5*658d439bSTaku Izumi  * This program is free software; you can redistribute it and/or modify it
6*658d439bSTaku Izumi  * under the terms and conditions of the GNU General Public License,
7*658d439bSTaku Izumi  * version 2, as published by the Free Software Foundation.
8*658d439bSTaku Izumi  *
9*658d439bSTaku Izumi  * This program is distributed in the hope it will be useful, but WITHOUT
10*658d439bSTaku Izumi  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11*658d439bSTaku Izumi  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12*658d439bSTaku Izumi  * more details.
13*658d439bSTaku Izumi  *
14*658d439bSTaku Izumi  * You should have received a copy of the GNU General Public License along with
15*658d439bSTaku Izumi  * this program; if not, see <http://www.gnu.org/licenses/>.
16*658d439bSTaku Izumi  *
17*658d439bSTaku Izumi  * The full GNU General Public License is included in this distribution in
18*658d439bSTaku Izumi  * the file called "COPYING".
19*658d439bSTaku Izumi  *
20*658d439bSTaku Izumi  */
21*658d439bSTaku Izumi 
22*658d439bSTaku Izumi #include <linux/module.h>
23*658d439bSTaku Izumi #include <linux/types.h>
24*658d439bSTaku Izumi #include <linux/nls.h>
25*658d439bSTaku Izumi #include <linux/platform_device.h>
26*658d439bSTaku Izumi 
27*658d439bSTaku Izumi #include "fjes.h"
28*658d439bSTaku Izumi 
29*658d439bSTaku Izumi #define MAJ 1
30*658d439bSTaku Izumi #define MIN 0
31*658d439bSTaku Izumi #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
32*658d439bSTaku Izumi #define DRV_NAME	"fjes"
33*658d439bSTaku Izumi char fjes_driver_name[] = DRV_NAME;
34*658d439bSTaku Izumi char fjes_driver_version[] = DRV_VERSION;
35*658d439bSTaku Izumi static const char fjes_driver_string[] =
36*658d439bSTaku Izumi 		"FUJITSU Extended Socket Network Device Driver";
37*658d439bSTaku Izumi static const char fjes_copyright[] =
38*658d439bSTaku Izumi 		"Copyright (c) 2015 FUJITSU LIMITED";
39*658d439bSTaku Izumi 
40*658d439bSTaku Izumi MODULE_AUTHOR("Taku Izumi <izumi.taku@jp.fujitsu.com>");
41*658d439bSTaku Izumi MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver");
42*658d439bSTaku Izumi MODULE_LICENSE("GPL");
43*658d439bSTaku Izumi MODULE_VERSION(DRV_VERSION);
44*658d439bSTaku Izumi 
45*658d439bSTaku Izumi static int fjes_acpi_add(struct acpi_device *);
46*658d439bSTaku Izumi static int fjes_acpi_remove(struct acpi_device *);
47*658d439bSTaku Izumi static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*);
48*658d439bSTaku Izumi 
49*658d439bSTaku Izumi static int fjes_probe(struct platform_device *);
50*658d439bSTaku Izumi static int fjes_remove(struct platform_device *);
51*658d439bSTaku Izumi 
52*658d439bSTaku Izumi static const struct acpi_device_id fjes_acpi_ids[] = {
53*658d439bSTaku Izumi 	{"PNP0C02", 0},
54*658d439bSTaku Izumi 	{"", 0},
55*658d439bSTaku Izumi };
56*658d439bSTaku Izumi MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
57*658d439bSTaku Izumi 
58*658d439bSTaku Izumi static struct acpi_driver fjes_acpi_driver = {
59*658d439bSTaku Izumi 	.name = DRV_NAME,
60*658d439bSTaku Izumi 	.class = DRV_NAME,
61*658d439bSTaku Izumi 	.owner = THIS_MODULE,
62*658d439bSTaku Izumi 	.ids = fjes_acpi_ids,
63*658d439bSTaku Izumi 	.ops = {
64*658d439bSTaku Izumi 		.add = fjes_acpi_add,
65*658d439bSTaku Izumi 		.remove = fjes_acpi_remove,
66*658d439bSTaku Izumi 	},
67*658d439bSTaku Izumi };
68*658d439bSTaku Izumi 
69*658d439bSTaku Izumi static struct platform_driver fjes_driver = {
70*658d439bSTaku Izumi 	.driver = {
71*658d439bSTaku Izumi 		.name = DRV_NAME,
72*658d439bSTaku Izumi 		.owner = THIS_MODULE,
73*658d439bSTaku Izumi 	},
74*658d439bSTaku Izumi 	.probe = fjes_probe,
75*658d439bSTaku Izumi 	.remove = fjes_remove,
76*658d439bSTaku Izumi };
77*658d439bSTaku Izumi 
78*658d439bSTaku Izumi static struct resource fjes_resource[] = {
79*658d439bSTaku Izumi 	{
80*658d439bSTaku Izumi 		.flags = IORESOURCE_MEM,
81*658d439bSTaku Izumi 		.start = 0,
82*658d439bSTaku Izumi 		.end = 0,
83*658d439bSTaku Izumi 	},
84*658d439bSTaku Izumi 	{
85*658d439bSTaku Izumi 		.flags = IORESOURCE_IRQ,
86*658d439bSTaku Izumi 		.start = 0,
87*658d439bSTaku Izumi 		.end = 0,
88*658d439bSTaku Izumi 	},
89*658d439bSTaku Izumi };
90*658d439bSTaku Izumi 
91*658d439bSTaku Izumi static int fjes_acpi_add(struct acpi_device *device)
92*658d439bSTaku Izumi {
93*658d439bSTaku Izumi 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
94*658d439bSTaku Izumi 	char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
95*658d439bSTaku Izumi 	struct platform_device *plat_dev;
96*658d439bSTaku Izumi 	union acpi_object *str;
97*658d439bSTaku Izumi 	acpi_status status;
98*658d439bSTaku Izumi 	int result;
99*658d439bSTaku Izumi 
100*658d439bSTaku Izumi 	status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
101*658d439bSTaku Izumi 	if (ACPI_FAILURE(status))
102*658d439bSTaku Izumi 		return -ENODEV;
103*658d439bSTaku Izumi 
104*658d439bSTaku Izumi 	str = buffer.pointer;
105*658d439bSTaku Izumi 	result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
106*658d439bSTaku Izumi 				 str->string.length, UTF16_LITTLE_ENDIAN,
107*658d439bSTaku Izumi 				 str_buf, sizeof(str_buf) - 1);
108*658d439bSTaku Izumi 	str_buf[result] = 0;
109*658d439bSTaku Izumi 
110*658d439bSTaku Izumi 	if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
111*658d439bSTaku Izumi 		kfree(buffer.pointer);
112*658d439bSTaku Izumi 		return -ENODEV;
113*658d439bSTaku Izumi 	}
114*658d439bSTaku Izumi 	kfree(buffer.pointer);
115*658d439bSTaku Izumi 
116*658d439bSTaku Izumi 	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
117*658d439bSTaku Izumi 				     fjes_get_acpi_resource, fjes_resource);
118*658d439bSTaku Izumi 	if (ACPI_FAILURE(status))
119*658d439bSTaku Izumi 		return -ENODEV;
120*658d439bSTaku Izumi 
121*658d439bSTaku Izumi 	/* create platform_device */
122*658d439bSTaku Izumi 	plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
123*658d439bSTaku Izumi 						   ARRAY_SIZE(fjes_resource));
124*658d439bSTaku Izumi 	device->driver_data = plat_dev;
125*658d439bSTaku Izumi 
126*658d439bSTaku Izumi 	return 0;
127*658d439bSTaku Izumi }
128*658d439bSTaku Izumi 
129*658d439bSTaku Izumi static int fjes_acpi_remove(struct acpi_device *device)
130*658d439bSTaku Izumi {
131*658d439bSTaku Izumi 	struct platform_device *plat_dev;
132*658d439bSTaku Izumi 
133*658d439bSTaku Izumi 	plat_dev = (struct platform_device *)acpi_driver_data(device);
134*658d439bSTaku Izumi 	platform_device_unregister(plat_dev);
135*658d439bSTaku Izumi 
136*658d439bSTaku Izumi 	return 0;
137*658d439bSTaku Izumi }
138*658d439bSTaku Izumi 
139*658d439bSTaku Izumi static acpi_status
140*658d439bSTaku Izumi fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
141*658d439bSTaku Izumi {
142*658d439bSTaku Izumi 	struct acpi_resource_address32 *addr;
143*658d439bSTaku Izumi 	struct acpi_resource_irq *irq;
144*658d439bSTaku Izumi 	struct resource *res = data;
145*658d439bSTaku Izumi 
146*658d439bSTaku Izumi 	switch (acpi_res->type) {
147*658d439bSTaku Izumi 	case ACPI_RESOURCE_TYPE_ADDRESS32:
148*658d439bSTaku Izumi 		addr = &acpi_res->data.address32;
149*658d439bSTaku Izumi 		res[0].start = addr->address.minimum;
150*658d439bSTaku Izumi 		res[0].end = addr->address.minimum +
151*658d439bSTaku Izumi 			addr->address.address_length - 1;
152*658d439bSTaku Izumi 		break;
153*658d439bSTaku Izumi 
154*658d439bSTaku Izumi 	case ACPI_RESOURCE_TYPE_IRQ:
155*658d439bSTaku Izumi 		irq = &acpi_res->data.irq;
156*658d439bSTaku Izumi 		if (irq->interrupt_count != 1)
157*658d439bSTaku Izumi 			return AE_ERROR;
158*658d439bSTaku Izumi 		res[1].start = irq->interrupts[0];
159*658d439bSTaku Izumi 		res[1].end = irq->interrupts[0];
160*658d439bSTaku Izumi 		break;
161*658d439bSTaku Izumi 
162*658d439bSTaku Izumi 	default:
163*658d439bSTaku Izumi 		break;
164*658d439bSTaku Izumi 	}
165*658d439bSTaku Izumi 
166*658d439bSTaku Izumi 	return AE_OK;
167*658d439bSTaku Izumi }
168*658d439bSTaku Izumi 
169*658d439bSTaku Izumi /* fjes_probe - Device Initialization Routine */
170*658d439bSTaku Izumi static int fjes_probe(struct platform_device *plat_dev)
171*658d439bSTaku Izumi {
172*658d439bSTaku Izumi 	return 0;
173*658d439bSTaku Izumi }
174*658d439bSTaku Izumi 
175*658d439bSTaku Izumi /* fjes_remove - Device Removal Routine */
176*658d439bSTaku Izumi static int fjes_remove(struct platform_device *plat_dev)
177*658d439bSTaku Izumi {
178*658d439bSTaku Izumi 	return 0;
179*658d439bSTaku Izumi }
180*658d439bSTaku Izumi 
181*658d439bSTaku Izumi /* fjes_init_module - Driver Registration Routine */
182*658d439bSTaku Izumi static int __init fjes_init_module(void)
183*658d439bSTaku Izumi {
184*658d439bSTaku Izumi 	int result;
185*658d439bSTaku Izumi 
186*658d439bSTaku Izumi 	pr_info("%s - version %s - %s\n",
187*658d439bSTaku Izumi 		fjes_driver_string, fjes_driver_version, fjes_copyright);
188*658d439bSTaku Izumi 
189*658d439bSTaku Izumi 	result = platform_driver_register(&fjes_driver);
190*658d439bSTaku Izumi 	if (result < 0)
191*658d439bSTaku Izumi 		return result;
192*658d439bSTaku Izumi 
193*658d439bSTaku Izumi 	result = acpi_bus_register_driver(&fjes_acpi_driver);
194*658d439bSTaku Izumi 	if (result < 0)
195*658d439bSTaku Izumi 		goto fail_acpi_driver;
196*658d439bSTaku Izumi 
197*658d439bSTaku Izumi 	return 0;
198*658d439bSTaku Izumi 
199*658d439bSTaku Izumi fail_acpi_driver:
200*658d439bSTaku Izumi 	platform_driver_unregister(&fjes_driver);
201*658d439bSTaku Izumi 	return result;
202*658d439bSTaku Izumi }
203*658d439bSTaku Izumi 
204*658d439bSTaku Izumi module_init(fjes_init_module);
205*658d439bSTaku Izumi 
206*658d439bSTaku Izumi /* fjes_exit_module - Driver Exit Cleanup Routine */
207*658d439bSTaku Izumi static void __exit fjes_exit_module(void)
208*658d439bSTaku Izumi {
209*658d439bSTaku Izumi 	acpi_bus_unregister_driver(&fjes_acpi_driver);
210*658d439bSTaku Izumi 	platform_driver_unregister(&fjes_driver);
211*658d439bSTaku Izumi }
212*658d439bSTaku Izumi 
213*658d439bSTaku Izumi module_exit(fjes_exit_module);
214