125b6a6f1Skrish_iyer /*
27a160a86SAdrien Destugues * Copyright 2018-2021 Haiku, Inc. All rights reserved.
325b6a6f1Skrish_iyer * Distributed under the terms of the MIT License.
425b6a6f1Skrish_iyer *
525b6a6f1Skrish_iyer * Authors:
625b6a6f1Skrish_iyer * B Krishnan Iyer, krishnaniyer97@gmail.com
77a160a86SAdrien Destugues * Adrien Destugues, pulkomandy@pulkomandy.tk
825b6a6f1Skrish_iyer */
925b6a6f1Skrish_iyer #include "mmc_bus.h"
1025b6a6f1Skrish_iyer
1125b6a6f1Skrish_iyer
12ff76d2dfSAdrien Destugues #define MMC_BUS_DEVICE_NAME "bus_managers/mmc_bus/device/v1"
13ff76d2dfSAdrien Destugues
14ff76d2dfSAdrien Destugues
1525b6a6f1Skrish_iyer device_manager_info* gDeviceManager = NULL;
1625b6a6f1Skrish_iyer
1725b6a6f1Skrish_iyer
1825b6a6f1Skrish_iyer static status_t
mmc_bus_init(device_node * node,void ** _device)1925b6a6f1Skrish_iyer mmc_bus_init(device_node* node, void** _device)
2025b6a6f1Skrish_iyer {
2125b6a6f1Skrish_iyer CALLED();
2225b6a6f1Skrish_iyer MMCBus* device = new(std::nothrow) MMCBus(node);
2325b6a6f1Skrish_iyer if (device == NULL) {
2425b6a6f1Skrish_iyer ERROR("Unable to allocate MMC bus\n");
2525b6a6f1Skrish_iyer return B_NO_MEMORY;
2625b6a6f1Skrish_iyer }
2725b6a6f1Skrish_iyer
2825b6a6f1Skrish_iyer status_t result = device->InitCheck();
2925b6a6f1Skrish_iyer if (result != B_OK) {
3025b6a6f1Skrish_iyer TRACE("failed to set up mmc bus device object\n");
3125b6a6f1Skrish_iyer return result;
3225b6a6f1Skrish_iyer }
3325b6a6f1Skrish_iyer TRACE("MMC bus object created\n");
3425b6a6f1Skrish_iyer
3525b6a6f1Skrish_iyer *_device = device;
3625b6a6f1Skrish_iyer return B_OK;
3725b6a6f1Skrish_iyer }
3825b6a6f1Skrish_iyer
3925b6a6f1Skrish_iyer
4025b6a6f1Skrish_iyer static void
mmc_bus_uninit(void * _device)4125b6a6f1Skrish_iyer mmc_bus_uninit(void* _device)
4225b6a6f1Skrish_iyer {
4325b6a6f1Skrish_iyer CALLED();
4425b6a6f1Skrish_iyer MMCBus* device = (MMCBus*)_device;
4525b6a6f1Skrish_iyer delete device;
4625b6a6f1Skrish_iyer }
4725b6a6f1Skrish_iyer
4825b6a6f1Skrish_iyer
49dedbe94eSAdrien Destugues static status_t
mmc_bus_register_child(void * _device)50dedbe94eSAdrien Destugues mmc_bus_register_child(void* _device)
51dedbe94eSAdrien Destugues {
5224136793SAdrien Destugues // Nothing to do, child devices are registered by the scanning thread
53dedbe94eSAdrien Destugues return B_OK;
54dedbe94eSAdrien Destugues }
55dedbe94eSAdrien Destugues
56dedbe94eSAdrien Destugues
5725b6a6f1Skrish_iyer static void
mmc_bus_removed(void * _device)5825b6a6f1Skrish_iyer mmc_bus_removed(void* _device)
5925b6a6f1Skrish_iyer {
6025b6a6f1Skrish_iyer CALLED();
6125b6a6f1Skrish_iyer }
6225b6a6f1Skrish_iyer
6325b6a6f1Skrish_iyer
6425b6a6f1Skrish_iyer status_t
mmc_bus_added_device(device_node * parent)6525b6a6f1Skrish_iyer mmc_bus_added_device(device_node* parent)
6625b6a6f1Skrish_iyer {
6725b6a6f1Skrish_iyer CALLED();
6825b6a6f1Skrish_iyer
6925b6a6f1Skrish_iyer device_attr attributes[] = {
70*215b685fSX512 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "mmc"}},
71*215b685fSX512 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "MMC bus root"}},
7225b6a6f1Skrish_iyer { NULL }
7325b6a6f1Skrish_iyer };
7425b6a6f1Skrish_iyer
75ff76d2dfSAdrien Destugues return gDeviceManager->register_node(parent, MMC_BUS_DEVICE_NAME,
7625b6a6f1Skrish_iyer attributes, NULL, NULL);
7725b6a6f1Skrish_iyer }
7825b6a6f1Skrish_iyer
7925b6a6f1Skrish_iyer
8025b6a6f1Skrish_iyer static status_t
mmc_bus_execute_command(device_node * node,void * cookie,uint16_t rca,uint8_t command,uint32_t argument,uint32_t * result)815ec64c5cSAdrien Destugues mmc_bus_execute_command(device_node* node, void* cookie, uint16_t rca,
825ec64c5cSAdrien Destugues uint8_t command, uint32_t argument, uint32_t* result)
8362eaf4c0SAdrien Destugues {
8462eaf4c0SAdrien Destugues TRACE("In mmc_bus_execute_command\n");
8562eaf4c0SAdrien Destugues
8674b60970SAnarchos MMCBus* bus = (MMCBus*)cookie;
8774b60970SAnarchos
8874b60970SAnarchos bus->AcquireBus();
89522c141dSAdrien Destugues status_t error = bus->ExecuteCommand(rca, command, argument, result);
9074b60970SAnarchos bus->ReleaseBus();
915ec64c5cSAdrien Destugues
9274b60970SAnarchos return error;
9374b60970SAnarchos }
9474b60970SAnarchos
9574b60970SAnarchos
9674b60970SAnarchos static status_t
mmc_bus_do_io(device_node * node,void * cookie,uint16_t rca,uint8_t command,IOOperation * operation,bool offsetAsSectors)975ec64c5cSAdrien Destugues mmc_bus_do_io(device_node* node, void* cookie, uint16_t rca, uint8_t command,
98d1fee57dSAdrien Destugues IOOperation* operation, bool offsetAsSectors)
9974b60970SAnarchos {
10074b60970SAnarchos MMCBus* bus = (MMCBus*)cookie;
1017a160a86SAdrien Destugues status_t result = B_OK;
1027a160a86SAdrien Destugues
1035ec64c5cSAdrien Destugues bus->AcquireBus();
104d1fee57dSAdrien Destugues result = bus->DoIO(rca, command, operation, offsetAsSectors);
10574b60970SAnarchos bus->ReleaseBus();
1065ec64c5cSAdrien Destugues
10774b60970SAnarchos return result;
10862eaf4c0SAdrien Destugues }
10962eaf4c0SAdrien Destugues
11062eaf4c0SAdrien Destugues
11134552f8eSAdrien Destugues static void
mmc_bus_set_width(device_node * node,void * cookie,int width)1125ec64c5cSAdrien Destugues mmc_bus_set_width(device_node* node, void* cookie, int width)
11334552f8eSAdrien Destugues {
11434552f8eSAdrien Destugues MMCBus* bus = (MMCBus*)cookie;
11534552f8eSAdrien Destugues
11634552f8eSAdrien Destugues bus->AcquireBus();
11734552f8eSAdrien Destugues bus->SetBusWidth(width);
11834552f8eSAdrien Destugues bus->ReleaseBus();
11934552f8eSAdrien Destugues }
12034552f8eSAdrien Destugues
12134552f8eSAdrien Destugues
12262eaf4c0SAdrien Destugues static status_t
std_ops(int32 op,...)12325b6a6f1Skrish_iyer std_ops(int32 op, ...)
12425b6a6f1Skrish_iyer {
12525b6a6f1Skrish_iyer switch (op) {
12625b6a6f1Skrish_iyer case B_MODULE_INIT:
12725b6a6f1Skrish_iyer // Nothing to do
12825b6a6f1Skrish_iyer case B_MODULE_UNINIT:
12925b6a6f1Skrish_iyer return B_OK;
13025b6a6f1Skrish_iyer
13125b6a6f1Skrish_iyer default:
13225b6a6f1Skrish_iyer break;
13325b6a6f1Skrish_iyer }
13425b6a6f1Skrish_iyer
13525b6a6f1Skrish_iyer return B_ERROR;
13625b6a6f1Skrish_iyer }
13725b6a6f1Skrish_iyer
13825b6a6f1Skrish_iyer
13925b6a6f1Skrish_iyer driver_module_info mmc_bus_device_module = {
14025b6a6f1Skrish_iyer {
141ff76d2dfSAdrien Destugues MMC_BUS_DEVICE_NAME,
14225b6a6f1Skrish_iyer 0,
14325b6a6f1Skrish_iyer std_ops
14425b6a6f1Skrish_iyer },
14525b6a6f1Skrish_iyer NULL, // supported devices
14625b6a6f1Skrish_iyer NULL, // register node
14725b6a6f1Skrish_iyer mmc_bus_init,
14825b6a6f1Skrish_iyer mmc_bus_uninit,
149dedbe94eSAdrien Destugues mmc_bus_register_child,
15025b6a6f1Skrish_iyer NULL, // rescan
15125b6a6f1Skrish_iyer mmc_bus_removed,
15225b6a6f1Skrish_iyer NULL, // suspend
15325b6a6f1Skrish_iyer NULL // resume
15425b6a6f1Skrish_iyer };
15525b6a6f1Skrish_iyer
15625b6a6f1Skrish_iyer
15762eaf4c0SAdrien Destugues mmc_device_interface mmc_bus_controller_module = {
15862eaf4c0SAdrien Destugues {
15925b6a6f1Skrish_iyer {
160ff76d2dfSAdrien Destugues MMC_BUS_MODULE_NAME,
16125b6a6f1Skrish_iyer 0,
16225b6a6f1Skrish_iyer &std_ops
16325b6a6f1Skrish_iyer },
16425b6a6f1Skrish_iyer
16525b6a6f1Skrish_iyer NULL, // supported devices
16625b6a6f1Skrish_iyer mmc_bus_added_device,
16725b6a6f1Skrish_iyer NULL,
16825b6a6f1Skrish_iyer NULL,
16925b6a6f1Skrish_iyer NULL
17062eaf4c0SAdrien Destugues },
17174b60970SAnarchos mmc_bus_execute_command,
17234552f8eSAdrien Destugues mmc_bus_do_io,
17334552f8eSAdrien Destugues mmc_bus_set_width
17425b6a6f1Skrish_iyer };
17525b6a6f1Skrish_iyer
17625b6a6f1Skrish_iyer
17725b6a6f1Skrish_iyer module_dependency module_dependencies[] = {
17825b6a6f1Skrish_iyer { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
17925b6a6f1Skrish_iyer {}
18025b6a6f1Skrish_iyer };
18125b6a6f1Skrish_iyer
18225b6a6f1Skrish_iyer
18325b6a6f1Skrish_iyer module_info* modules[] = {
18425b6a6f1Skrish_iyer (module_info*)&mmc_bus_controller_module,
18525b6a6f1Skrish_iyer (module_info*)&mmc_bus_device_module,
18625b6a6f1Skrish_iyer NULL
18725b6a6f1Skrish_iyer };
188